1178828Sdfr/*-
2178828Sdfr * Copyright (c) 2008 Doug Rabson
3178828Sdfr * All rights reserved.
4178828Sdfr *
5178828Sdfr * Redistribution and use in source and binary forms, with or without
6178828Sdfr * modification, are permitted provided that the following conditions
7178828Sdfr * are met:
8178828Sdfr * 1. Redistributions of source code must retain the above copyright
9178828Sdfr *    notice, this list of conditions and the following disclaimer.
10178828Sdfr * 2. Redistributions in binary form must reproduce the above copyright
11178828Sdfr *    notice, this list of conditions and the following disclaimer in the
12178828Sdfr *    documentation and/or other materials provided with the distribution.
13178828Sdfr *
14178828Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15178828Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16178828Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17178828Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18178828Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19178828Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20178828Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21178828Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22178828Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23178828Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24178828Sdfr * SUCH DAMAGE.
25178828Sdfr *
26178828Sdfr * $FreeBSD$
27178828Sdfr */
28178828Sdfr
29178828Sdfr#include <gssapi/gssapi.h>
30178828Sdfr#include <stdlib.h>
31178828Sdfr#include <string.h>
32178828Sdfr
33178828Sdfr#include "utils.h"
34178828Sdfr
35178828SdfrOM_uint32
36178828Sdfrgss_decapsulate_token(const gss_buffer_t input_token, gss_OID oid,
37178828Sdfr    gss_buffer_t output_token)
38178828Sdfr{
39178828Sdfr	unsigned char *p = input_token->value;
40178828Sdfr	size_t len = input_token->length;
41178828Sdfr	size_t a, b;
42178828Sdfr	gss_OID_desc mech_oid;
43178828Sdfr
44178828Sdfr	_gss_buffer_zero(output_token);
45178828Sdfr
46178828Sdfr	/*
47178828Sdfr	 * Token must start with [APPLICATION 0] SEQUENCE.
48178828Sdfr	 */
49178828Sdfr	if (len == 0 || *p != 0x60)
50178828Sdfr		return (GSS_S_DEFECTIVE_TOKEN);
51178828Sdfr	p++;
52178828Sdfr	len--;
53178828Sdfr
54178828Sdfr	/*
55178828Sdfr	 * Decode the length and make sure it agrees with the
56178828Sdfr	 * token length.
57178828Sdfr	 */
58178828Sdfr	if (len == 0)
59178828Sdfr		return (GSS_S_DEFECTIVE_TOKEN);
60178828Sdfr	if ((*p & 0x80) == 0) {
61178828Sdfr		a = *p;
62178828Sdfr		p++;
63178828Sdfr		len--;
64178828Sdfr	} else {
65178828Sdfr		b = *p & 0x7f;
66178828Sdfr		p++;
67178828Sdfr		len--;
68178828Sdfr		if (len < b)
69178828Sdfr			return (GSS_S_DEFECTIVE_TOKEN);
70178828Sdfr		a = 0;
71178828Sdfr		while (b) {
72178828Sdfr			a = (a << 8) | *p;
73178828Sdfr			p++;
74178828Sdfr			len--;
75178828Sdfr			b--;
76178828Sdfr		}
77178828Sdfr	}
78178828Sdfr	if (a != len)
79178828Sdfr		return (GSS_S_DEFECTIVE_TOKEN);
80178828Sdfr
81178828Sdfr	/*
82178828Sdfr	 * Decode the OID for the mechanism. Simplify life by
83178828Sdfr	 * assuming that the OID length is less than 128 bytes.
84178828Sdfr	 */
85178828Sdfr	if (len < 2 || *p != 0x06)
86178828Sdfr		return (GSS_S_DEFECTIVE_TOKEN);
87178828Sdfr	if ((p[1] & 0x80) || p[1] > (len - 2))
88178828Sdfr		return (GSS_S_DEFECTIVE_TOKEN);
89178828Sdfr	mech_oid.length = p[1];
90178828Sdfr	p += 2;
91178828Sdfr	len -= 2;
92178828Sdfr	mech_oid.elements = p;
93178828Sdfr
94178828Sdfr	if (!gss_oid_equal(&mech_oid, oid))
95178828Sdfr		return (GSS_S_FAILURE);
96178828Sdfr
97178828Sdfr	p += mech_oid.length;
98178828Sdfr	len -= mech_oid.length;
99178828Sdfr
100178828Sdfr	output_token->length = len;
101178828Sdfr	output_token->value = malloc(len);
102178828Sdfr	if (!output_token->value)
103178828Sdfr		return (GSS_S_DEFECTIVE_TOKEN);
104178828Sdfr	memcpy(output_token->value, p, len);
105178828Sdfr
106178828Sdfr	return (GSS_S_COMPLETE);
107178828Sdfr}
108