1192908Szml/*
2192908Szml * Copyright (c) 1997 - 2003 Kungliga Tekniska H��gskolan
3192908Szml * (Royal Institute of Technology, Stockholm, Sweden).
4192908Szml * All rights reserved.
5192908Szml *
6192908Szml * Redistribution and use in source and binary forms, with or without
7192908Szml * modification, are permitted provided that the following conditions
8192908Szml * are met:
9192908Szml *
10192908Szml * 1. Redistributions of source code must retain the above copyright
11192908Szml *    notice, this list of conditions and the following disclaimer.
12192908Szml *
13192908Szml * 2. Redistributions in binary form must reproduce the above copyright
14192908Szml *    notice, this list of conditions and the following disclaimer in the
15192908Szml *    documentation and/or other materials provided with the distribution.
16192908Szml *
17192908Szml * 3. Neither the name of the Institute nor the names of its contributors
18192908Szml *    may be used to endorse or promote products derived from this software
19192908Szml *    without specific prior written permission.
20192908Szml *
21192908Szml * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22192908Szml * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23192908Szml * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24192908Szml * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25192908Szml * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26192908Szml * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27192908Szml * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28192908Szml * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29296929Scem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30192908Szml * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31192908Szml * SUCH DAMAGE.
32192908Szml */
33192908Szml
34296927Scem#include "gsskrb5_locl.h"
35296927Scem
36192908Szmlvoid
37192908Szml_gssapi_encap_length (size_t data_len,
38192908Szml		      size_t *len,
39192908Szml		      size_t *total_len,
40296927Scem		      const gss_OID mech)
41192908Szml{
42192908Szml    size_t len_len;
43192908Szml
44192908Szml    *len = 1 + 1 + mech->length + data_len;
45192908Szml
46192908Szml    len_len = der_length_len(*len);
47296927Scem
48296927Scem    *total_len = 1 + len_len + *len;
49192908Szml}
50192908Szml
51192908Szmlvoid
52192908Szml_gsskrb5_encap_length (size_t data_len,
53296927Scem			  size_t *len,
54192908Szml			  size_t *total_len,
55192908Szml			  const gss_OID mech)
56192978Szml{
57192978Szml    _gssapi_encap_length(data_len + 2, len, total_len, mech);
58192978Szml}
59192978Szml
60192978Szmlvoid *
61192908Szml_gsskrb5_make_header (void *ptr,
62192908Szml			 size_t len,
63192908Szml			 const void *type,
64192908Szml			 const gss_OID mech)
65192908Szml{
66192908Szml    u_char *p = ptr;
67192908Szml    p = _gssapi_make_mech_header(p, len, mech);
68192908Szml    memcpy (p, type, 2);
69192908Szml    p += 2;
70192908Szml    return p;
71192908Szml}
72192908Szml
73192908Szmlvoid *
74192978Szml_gssapi_make_mech_header(void *ptr,
75192978Szml			 size_t len,
76192908Szml			 const gss_OID mech)
77192908Szml{
78192978Szml    u_char *p = ptr;
79192978Szml    int e;
80192908Szml    size_t len_len, foo;
81192908Szml
82192908Szml    *p++ = 0x60;
83192908Szml    len_len = der_length_len(len);
84192908Szml    e = der_put_length (p + len_len - 1, len_len, len, &foo);
85192978Szml    if(e || foo != len_len)
86296927Scem	abort ();
87296927Scem    p += len_len;
88296927Scem    *p++ = 0x06;
89296927Scem    *p++ = mech->length;
90296927Scem    memcpy (p, mech->elements, mech->length);
91296927Scem    p += mech->length;
92296927Scem    return p;
93296927Scem}
94296927Scem
95296927Scem/*
96296927Scem * Give it a krb5_data and it will encapsulate with extra GSS-API wrappings.
97296927Scem */
98296927Scem
99296927ScemOM_uint32
100296927Scem_gssapi_encapsulate(
101296927Scem    OM_uint32 *minor_status,
102296927Scem    const krb5_data *in_data,
103296927Scem    gss_buffer_t output_token,
104296927Scem    const gss_OID mech
105296927Scem)
106296927Scem{
107296927Scem    size_t len, outer_len;
108296927Scem    void *p;
109296927Scem
110296927Scem    _gssapi_encap_length (in_data->length, &len, &outer_len, mech);
111296927Scem
112296927Scem    output_token->length = outer_len;
113296927Scem    output_token->value  = malloc (outer_len);
114296927Scem    if (output_token->value == NULL) {
115296927Scem	*minor_status = ENOMEM;
116296927Scem	return GSS_S_FAILURE;
117296927Scem    }
118296927Scem
119296927Scem    p = _gssapi_make_mech_header (output_token->value, len, mech);
120296927Scem    memcpy (p, in_data->data, in_data->length);
121296927Scem    return GSS_S_COMPLETE;
122192978Szml}
123197310Sbrueffer
124192908Szml/*
125192908Szml * Give it a krb5_data and it will encapsulate with extra GSS-API krb5
126192908Szml * wrappings.
127192908Szml */
128192908Szml
129205076SuqsOM_uint32
130192908Szml_gsskrb5_encapsulate(
131192908Szml			OM_uint32 *minor_status,
132192908Szml			const krb5_data *in_data,
133192908Szml			gss_buffer_t output_token,
134192908Szml			const void *type,
135192908Szml			const gss_OID mech
136192908Szml)
137192908Szml{
138192908Szml    size_t len, outer_len;
139192908Szml    u_char *p;
140192908Szml
141205076Suqs    _gsskrb5_encap_length (in_data->length, &len, &outer_len, mech);
142192908Szml
143192908Szml    output_token->length = outer_len;
144192908Szml    output_token->value  = malloc (outer_len);
145192908Szml    if (output_token->value == NULL) {
146192978Szml	*minor_status = ENOMEM;
147192978Szml	return GSS_S_FAILURE;
148192908Szml    }
149192908Szml
150197310Sbrueffer    p = _gsskrb5_make_header (output_token->value, len, type, mech);
151192908Szml    memcpy (p, in_data->data, in_data->length);
152296927Scem    return GSS_S_COMPLETE;
153197310Sbrueffer}
154296927Scem