00218617a07b0fb479feccfdceff0c82d5f94bab
[sfrench/samba-autobuild/.git] / source4 / heimdal / lib / gssapi / krb5 / export_sec_context.c
1 /*
2  * Copyright (c) 1999 - 2003 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/gsskrb5_locl.h"
35
36 RCSID("$Id: export_sec_context.c 19031 2006-11-13 18:02:57Z lha $");
37
38 OM_uint32
39 _gsskrb5_export_sec_context (
40     OM_uint32 * minor_status,
41     gss_ctx_id_t * context_handle,
42     gss_buffer_t interprocess_token
43     )
44 {
45     krb5_context context;
46     const gsskrb5_ctx ctx = (const gsskrb5_ctx) *context_handle;
47     krb5_storage *sp;
48     krb5_auth_context ac;
49     OM_uint32 ret = GSS_S_COMPLETE;
50     krb5_data data;
51     gss_buffer_desc buffer;
52     int flags;
53     OM_uint32 minor;
54     krb5_error_code kret;
55
56     GSSAPI_KRB5_INIT (&context);
57
58     HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
59
60     if (!(ctx->flags & GSS_C_TRANS_FLAG)) {
61         HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
62         *minor_status = 0;
63         return GSS_S_UNAVAILABLE;
64     }
65
66     sp = krb5_storage_emem ();
67     if (sp == NULL) {
68         HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
69         *minor_status = ENOMEM;
70         return GSS_S_FAILURE;
71     }
72     ac = ctx->auth_context;
73
74     /* flagging included fields */
75
76     flags = 0;
77     if (ac->local_address)
78         flags |= SC_LOCAL_ADDRESS;
79     if (ac->remote_address)
80         flags |= SC_REMOTE_ADDRESS;
81     if (ac->keyblock)
82         flags |= SC_KEYBLOCK;
83     if (ac->local_subkey)
84         flags |= SC_LOCAL_SUBKEY;
85     if (ac->remote_subkey)
86         flags |= SC_REMOTE_SUBKEY;
87
88     kret = krb5_store_int32 (sp, flags);
89     if (kret) {
90         *minor_status = kret;
91         goto failure;
92     }
93
94     /* marshall auth context */
95
96     kret = krb5_store_int32 (sp, ac->flags);
97     if (kret) {
98         *minor_status = kret;
99         goto failure;
100     }
101     if (ac->local_address) {
102         kret = krb5_store_address (sp, *ac->local_address);
103         if (kret) {
104             *minor_status = kret;
105             goto failure;
106         }
107     }
108     if (ac->remote_address) {
109         kret = krb5_store_address (sp, *ac->remote_address);
110         if (kret) {
111             *minor_status = kret;
112             goto failure;
113         }
114     }
115     kret = krb5_store_int16 (sp, ac->local_port);
116     if (kret) {
117         *minor_status = kret;
118         goto failure;
119     }
120     kret = krb5_store_int16 (sp, ac->remote_port);
121     if (kret) {
122         *minor_status = kret;
123         goto failure;
124     }
125     if (ac->keyblock) {
126         kret = krb5_store_keyblock (sp, *ac->keyblock);
127         if (kret) {
128             *minor_status = kret;
129             goto failure;
130         }
131     }
132     if (ac->local_subkey) {
133         kret = krb5_store_keyblock (sp, *ac->local_subkey);
134         if (kret) {
135             *minor_status = kret;
136             goto failure;
137         }
138     }
139     if (ac->remote_subkey) {
140         kret = krb5_store_keyblock (sp, *ac->remote_subkey);
141         if (kret) {
142             *minor_status = kret;
143             goto failure;
144         }
145     }
146     kret = krb5_store_int32 (sp, ac->local_seqnumber);
147         if (kret) {
148             *minor_status = kret;
149             goto failure;
150         }
151     kret = krb5_store_int32 (sp, ac->remote_seqnumber);
152         if (kret) {
153             *minor_status = kret;
154             goto failure;
155         }
156
157     kret = krb5_store_int32 (sp, ac->keytype);
158     if (kret) {
159         *minor_status = kret;
160         goto failure;
161     }
162     kret = krb5_store_int32 (sp, ac->cksumtype);
163     if (kret) {
164         *minor_status = kret;
165         goto failure;
166     }
167
168     /* names */
169
170     ret = _gsskrb5_export_name (minor_status,
171                                 (gss_name_t)ctx->source, &buffer);
172     if (ret)
173         goto failure;
174     data.data   = buffer.value;
175     data.length = buffer.length;
176     kret = krb5_store_data (sp, data);
177     _gsskrb5_release_buffer (&minor, &buffer);
178     if (kret) {
179         *minor_status = kret;
180         goto failure;
181     }
182
183     ret = _gsskrb5_export_name (minor_status,
184                                 (gss_name_t)ctx->target, &buffer);
185     if (ret)
186         goto failure;
187     data.data   = buffer.value;
188     data.length = buffer.length;
189
190     ret = GSS_S_FAILURE;
191
192     kret = krb5_store_data (sp, data);
193     _gsskrb5_release_buffer (&minor, &buffer);
194     if (kret) {
195         *minor_status = kret;
196         goto failure;
197     }
198
199     kret = krb5_store_int32 (sp, ctx->flags);
200     if (kret) {
201         *minor_status = kret;
202         goto failure;
203     }
204     kret = krb5_store_int32 (sp, ctx->more_flags);
205     if (kret) {
206         *minor_status = kret;
207         goto failure;
208     }
209     kret = krb5_store_int32 (sp, ctx->lifetime);
210     if (kret) {
211         *minor_status = kret;
212         goto failure;
213     }
214     kret = _gssapi_msg_order_export(sp, ctx->order);
215     if (kret ) {
216         *minor_status = kret;
217         goto failure;
218     }
219
220     kret = krb5_storage_to_data (sp, &data);
221     krb5_storage_free (sp);
222     if (kret) {
223         HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
224         *minor_status = kret;
225         return GSS_S_FAILURE;
226     }
227     interprocess_token->length = data.length;
228     interprocess_token->value  = data.data;
229     HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
230     ret = _gsskrb5_delete_sec_context (minor_status, context_handle,
231                                        GSS_C_NO_BUFFER);
232     if (ret != GSS_S_COMPLETE)
233         _gsskrb5_release_buffer (NULL, interprocess_token);
234     *minor_status = 0;
235     return ret;
236  failure:
237     HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
238     krb5_storage_free (sp);
239     return ret;
240 }