spnego.c revision 07a4f0eace3b7b919936a342f63545b1b35eefe9
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * Copyright (C) 2006-2011 Internet Systems Consortium, Inc. ("ISC")
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * Permission to use, copy, modify, and/or distribute this software for any
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * purpose with or without fee is hereby granted, provided that the above
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * copyright notice and this permission notice appear in all copies.
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * PERFORMANCE OF THIS SOFTWARE.
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff/* $Id: spnego.c,v 1.20 2011/08/29 04:15:50 marka Exp $ */
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * Portable SPNEGO implementation.
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * This is part of a portable implementation of the SPNEGO protocol
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * (RFCs 2478 and 4178). This implementation uses the RFC 4178 ASN.1
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * module but is not a full implementation of the RFC 4178 protocol;
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * at the moment, we only support GSS-TSIG with Kerberos
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * authentication, so we only need enough of the SPNEGO protocol to
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * support that.
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * The files that make up this portable SPNEGO implementation are:
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * \li spnego.c (this file)
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * \li spnego.h (API SPNEGO exports to the rest of lib/dns)
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * \li spnego.asn1 (SPNEGO ASN.1 module)
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff * \li spnego_asn1.c (routines generated from spngo.asn1)
31fab17bcdbe302592a6c0dc5374ef56333ee879Michael Graff * \li spnego_asn1.pl (perl script to generate spnego_asn1.c)
3024dbecbac365171bc6de0f3fa04951d6558be3Michael Graff * Everything but the functions exported in spnego.h is static, to
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * avoid possible conflicts with other libraries (particularly Heimdal,
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * since much of this code comes from Heimdal by way of mod_auth_kerb).
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff * spnego_asn1.c is shipped as part of lib/dns because generating it
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * requires both Perl and the Heimdal ASN.1 compiler. See
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff * spnego_asn1.pl for further details. We've tried to eliminate all
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff * compiler warnings from the generated code, but you may see a few
439c0011e642fb1d26011116144af698125262dbMichael Graff * when using a compiler version we haven't tested yet.
31fab17bcdbe302592a6c0dc5374ef56333ee879Michael Graff * Portions of this code were derived from mod_auth_kerb and Heimdal.
31fab17bcdbe302592a6c0dc5374ef56333ee879Michael Graff * These packages are available from:
31fab17bcdbe302592a6c0dc5374ef56333ee879Michael Graff * and were released under the following licenses:
31fab17bcdbe302592a6c0dc5374ef56333ee879Michael Graff * ----------------------------------------------------------------
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * Copyright (c) 2004 Masarykova universita
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * (Masaryk University, Brno, Czech Republic)
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * All rights reserved.
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff * Redistribution and use in source and binary forms, with or without
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff * modification, are permitted provided that the following conditions are met:
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * 1. Redistributions of source code must retain the above copyright notice,
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * this list of conditions and the following disclaimer.
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * 2. Redistributions in binary form must reproduce the above copyright
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * notice, this list of conditions and the following disclaimer in the
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Graff * documentation and/or other materials provided with the distribution.
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * 3. Neither the name of the University nor the names of its contributors may
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * be used to endorse or promote products derived from this software
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * without specific prior written permission.
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
439c0011e642fb1d26011116144af698125262dbMichael Graff * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * POSSIBILITY OF SUCH DAMAGE.
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * ----------------------------------------------------------------
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * Copyright (c) 1997 - 2003 Kungliga Tekniska H�gskolan
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * (Royal Institute of Technology, Stockholm, Sweden).
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * All rights reserved.
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Graff * Redistribution and use in source and binary forms, with or without
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Graff * modification, are permitted provided that the following conditions
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Graff * 1. Redistributions of source code must retain the above copyright
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * notice, this list of conditions and the following disclaimer.
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Graff * 2. Redistributions in binary form must reproduce the above copyright
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Graff * notice, this list of conditions and the following disclaimer in the
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Graff * documentation and/or other materials provided with the distribution.
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * 3. Neither the name of the Institute nor the names of its contributors
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * may be used to endorse or promote products derived from this software
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * without specific prior written permission.
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
439c0011e642fb1d26011116144af698125262dbMichael Graff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * SUCH DAMAGE.
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * XXXSRA We should omit this file entirely in Makefile.in via autoconf,
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * but this will keep it from generating errors until that's written.
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * XXXSRA Some of the following files are almost certainly unnecessary,
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * but using this list (borrowed from gssapictx.c) gets rid of some
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * whacky compilation errors when building with MSVC and should be
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * harmless in any case.
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * The API we export
439c0011e642fb1d26011116144af698125262dbMichael Graff/* Generated from ../../../lib/asn1/asn1_err.et */
439c0011e642fb1d26011116144af698125262dbMichael Graff/* these may be brought in already via gssapi_krb5.h */
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Grafftypedef struct octet_string {
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Grafftypedef struct oid {
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Grafftypedef enum {
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Grafftypedef enum {
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff/* Universal tags */
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffder_get_length(const unsigned char *p, size_t len,
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffder_get_octet_string(const unsigned char *p, size_t len,
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffder_get_oid(const unsigned char *p, size_t len,
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffder_get_tag(const unsigned char *p, size_t len,
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffder_match_tag(const unsigned char *p, size_t len,
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffder_match_tag_and_length(const unsigned char *p, size_t len,
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffdecode_enumerated(const unsigned char *p, size_t len, void *num, size_t *size);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffdecode_octet_string(const unsigned char *, size_t, octet_string *, size_t *);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffder_put_int(unsigned char *p, size_t len, int val, size_t *);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffder_put_length(unsigned char *p, size_t len, size_t val, size_t *);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffder_put_octet_string(unsigned char *p, size_t len,
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffder_put_tag(unsigned char *p, size_t len, Der_class class, Der_type type,
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffder_put_length_and_tag(unsigned char *, size_t, size_t,
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffencode_enumerated(unsigned char *p, size_t len, const void *data, size_t *);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffencode_octet_string(unsigned char *p, size_t len,
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * Include stuff generated by the ASN.1 compiler.
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffstatic unsigned char gss_krb5_mech_oid_bytes[] = {
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffstatic gss_OID GSS_KRB5_MECH = &gss_krb5_mech_oid_desc;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffstatic unsigned char gss_mskrb5_mech_oid_bytes[] = {
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff 0x2a, 0x86, 0x48, 0x82, 0xf7, 0x12, 0x01, 0x02, 0x02
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffstatic gss_OID_desc gss_mskrb5_mech_oid_desc = {
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffstatic gss_OID GSS_MSKRB5_MECH = &gss_mskrb5_mech_oid_desc;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffstatic unsigned char gss_spnego_mech_oid_bytes[] = {
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffstatic gss_OID_desc gss_spnego_mech_oid_desc = {
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffstatic gss_OID GSS_SPNEGO_MECH = &gss_spnego_mech_oid_desc;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff unsigned char *,
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff unsigned char **,
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff unsigned char *p;
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff if (*p++ != 0x60)
439c0011e642fb1d26011116144af698125262dbMichael Graff if (*p++ != 0x06)
439c0011e642fb1d26011116144af698125262dbMichael Graff return (memcmp(p, oid->elements, oid->length));
439c0011e642fb1d26011116144af698125262dbMichael Graff * SPNEGO wrapper for Kerberos5 GSS-API kouril@ics.muni.cz, 2003 (mostly
439c0011e642fb1d26011116144af698125262dbMichael Graff * based on Heimdal code)
439c0011e642fb1d26011116144af698125262dbMichael Graff unsigned char **outbuf,
439c0011e642fb1d26011116144af698125262dbMichael Graff ret = der_put_length_and_tag(buf + buf_size - buf_len - 1,
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff memcpy(*outbuf, buf + buf_size - buf_len, buf_len);
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff resp.negState = malloc(sizeof(*resp.negState));
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff resp.negState = malloc(sizeof(*resp.negState));
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff resp.supportedMech = malloc(sizeof(*resp.supportedMech));
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff if (mech_token != NULL && mech_token->length != 0U) {
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff resp.responseToken = malloc(sizeof(*resp.responseToken));
439c0011e642fb1d26011116144af698125262dbMichael Graff resp.responseToken->length = mech_token->length;
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffgss_accept_sec_context_spnego(OM_uint32 *minor_status,
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff const gss_channel_bindings_t input_chan_bindings,
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff unsigned char *buf;
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * Before doing anything else, see whether this is a SPNEGO
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * PDU. If not, dispatch to the GSSAPI library and get out.
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff if (cmp_gss_type(input_token_buffer, GSS_SPNEGO_MECH))
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * If we get here, it's SPNEGO.
519b4a1a27c8b767a57a981dda69a3c6394bd49dMichael Graff ret = gssapi_spnego_decapsulate(minor_status, input_token_buffer,
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff ret = der_match_tag_and_length(buf, buf_size, ASN1_C_CONTEXT, CONS,
439c0011e642fb1d26011116144af698125262dbMichael Graff ret = decode_NegTokenInit(buf + taglen, len, &init_token, &ni_len);
519b4a1a27c8b767a57a981dda69a3c6394bd49dMichael Graff for (i = 0; !found && i < init_token.mechTypes.len; ++i) {
519b4a1a27c8b767a57a981dda69a3c6394bd49dMichael Graff ret = der_put_oid(mechbuf + sizeof(mechbuf) - 1,
439c0011e642fb1d26011116144af698125262dbMichael Graff return (send_reject(minor_status, output_token));
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff major_status = gss_accept_sec_context(minor_status,
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff ret = send_accept(&minor_status2, output_token, ot, pref);
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff if (*p++ != 0x60)
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff e = der_get_length(p, total_len - 1, &len, &len_len);
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff if (*p++ != 0x06)
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff e = der_get_length(p, total_len - 1 - len_len - 1,
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff if (memcmp(p, mech->elements, mech->length) != 0)
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff * Remove the GSS-API wrapping from `in_token' giving `buf and buf_size' Does
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * not copy data, so just free `in_token'.
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graffgssapi_spnego_decapsulate(OM_uint32 *minor_status,
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff unsigned char **buf,
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * All decoding functions take a pointer `p' to first position in which to
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * read, from the left, `len' which means the maximum number of characters we
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * are able to read, `ret' were the value will be returned and `size' where
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * the number of used bytes is stored. Either 0 or an error code is returned.
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffder_get_unsigned(const unsigned char *p, size_t len,
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff unsigned val = 0;
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graffder_get_int(const unsigned char *p, size_t len,
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff val = (signed char)*p++;
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graffder_get_length(const unsigned char *p, size_t len,
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff if (v < 128U) {
439c0011e642fb1d26011116144af698125262dbMichael Graff if (v == 0x80U) {
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graffder_get_octet_string(const unsigned char *p, size_t len,
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graffder_get_oid(const unsigned char *p, size_t len,
3024dbecbac365171bc6de0f3fa04951d6558be3Michael Graff data->components = malloc(len * sizeof(*data->components));
3024dbecbac365171bc6de0f3fa04951d6558be3Michael Graff unsigned u = 0;
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graffder_get_tag(const unsigned char *p, size_t len,
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffder_match_tag(const unsigned char *p, size_t len,
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff e = der_get_tag(p, len, &thisclass, &thistype, &thistag, &l);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffder_match_tag_and_length(const unsigned char *p, size_t len,
3024dbecbac365171bc6de0f3fa04951d6558be3Michael Graff e = der_match_tag(p, len, class, type, tag, &l);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff /* p += l; */
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffdecode_enumerated(const unsigned char *p, size_t len, void *num, size_t *size)
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff e = der_match_tag(p, len, ASN1_C_UNIV, PRIM, UT_Enumerated, &l);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffdecode_octet_string(const unsigned char *p, size_t len,
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff e = der_match_tag(p, len, ASN1_C_UNIV, PRIM, UT_OctetString, &l);
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff e = der_match_tag(p, len, ASN1_C_UNIV, PRIM, UT_OID, &l);
439c0011e642fb1d26011116144af698125262dbMichael Graff * All encoding functions take a pointer `p' to first position in which to
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff * write, from the right, `len' which means the maximum number of characters
439c0011e642fb1d26011116144af698125262dbMichael Graff * we are able to write. The function returns the number of characters
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff * written in `size' (if non-NULL). The return value is 0 or an error.
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graffder_put_unsigned(unsigned char *p, size_t len, unsigned val, size_t *size)
439c0011e642fb1d26011116144af698125262dbMichael Graff unsigned char *base = p;
439c0011e642fb1d26011116144af698125262dbMichael Graffder_put_int(unsigned char *p, size_t len, int val, size_t *size)
439c0011e642fb1d26011116144af698125262dbMichael Graff unsigned char *base = p;
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graffder_put_length(unsigned char *p, size_t len, size_t val, size_t *size)
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff *p = 0x80 | l;
439c0011e642fb1d26011116144af698125262dbMichael Graffder_put_octet_string(unsigned char *p, size_t len,
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff unsigned char *base = p;
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff *p-- = u % 128;
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff while (u > 0) {
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff *p-- = 40 * data->components[0] + data->components[1];
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graffder_put_tag(unsigned char *p, size_t len, Der_class class, Der_type type,
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff *p = (class << 6) | (type << 5) | tag; /* XXX */
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffder_put_length_and_tag(unsigned char *p, size_t len, size_t len_val,
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff Der_class class, Der_type type, int tag, size_t *size)
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff e = der_put_tag(p, len, class, type, tag, &l);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffencode_enumerated(unsigned char *p, size_t len, const void *data, size_t *size)
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff e = der_put_length_and_tag(p, len, l, ASN1_C_UNIV, PRIM, UT_Enumerated, &l);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffencode_octet_string(unsigned char *p, size_t len,
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff e = der_put_length_and_tag(p, len, l, ASN1_C_UNIV, PRIM, UT_OctetString, &l);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff e = der_put_length_and_tag(p, len, l, ASN1_C_UNIV, PRIM, UT_OID, &l);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff e = der_put_length(p + len_len - 1, len_len, len, &foo);
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff * Give it a krb5_data and it will encapsulate with extra GSS-API wrappings.
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graffgssapi_spnego_encapsulate(OM_uint32 * minor_status,
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff unsigned char *buf,
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff gssapi_encap_length(buf_size, &len, &outer_len, mech);
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff p = gssapi_mech_make_header(output_token->value, len, mech);
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff gss_release_buffer(minor_status, output_token);
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff * SPNEGO wrapper for Kerberos5 GSS-API kouril@ics.muni.cz, 2003 (mostly
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff * based on Heimdal code)
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graffadd_mech(MechTypeList * mech_list, gss_OID mech)
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff tmp = realloc(mech_list->val, (mech_list->len + 1) * sizeof(*tmp));
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff ret = der_get_oid(mech->elements, mech->length,
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * return the length of the mechanism in token or -1
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * (which implies that the token was bad - GSS_S_DEFECTIVE_TOKEN
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff if (*p++ != 0x60)
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff e = der_get_length (p, total_len - 1, &len, &len_len);
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff if (*p++ != 0x06)
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff e = der_get_length (p, total_len - 1 - len_len - 1,
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff const gss_channel_bindings_t input_chan_bindings,
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff gss_buffer_desc krb5_output_token = GSS_C_EMPTY_BUFFER;
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graff ret = add_mech(&token_init.mechTypes, GSS_KRB5_MECH);
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graff major_status = gss_init_sec_context(minor_status,
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff token_init.mechToken = malloc(sizeof(*token_init.mechToken));
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff token_init.mechToken->data = krb5_output_token.value;
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff token_init.mechToken->length = krb5_output_token.length;
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * The MS implementation of SPNEGO seems to not like the mechListMIC
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * field, so we omit it (it's optional anyway)
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff ret = der_put_length_and_tag(buf + buf_size - len - 1,
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff gss_release_buffer(&minor_status2, &krb5_output_token);
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff const gss_channel_bindings_t input_chan_bindings,
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff unsigned char *buf;
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff * SPNEGO doesn't include gss wrapping on SubsequentContextToken
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff * like the Kerberos 5 mech does. But lets check for it anyway.
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff mech_len = gssapi_krb5_get_mech(input_token->value,
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff } else if ((size_t)mech_len == GSS_KRB5_MECH->length &&
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff memcmp(GSS_KRB5_MECH->elements, p, mech_len) == 0)
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff else if ((size_t)mech_len == GSS_SPNEGO_MECH->length &&
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff memcmp(GSS_SPNEGO_MECH->elements, p, mech_len) == 0) {
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff ret = decode_NegTokenResp(buf + taglen, len, &resp, NULL);
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff ret = der_put_oid(oidbuf + sizeof(oidbuf) - 1,
f36a81c88493985ee2d1c53cc6fe88f4b00dbbc8Michael Graff sub_token.length = resp.responseToken->length;
time_rec);
if (ret) {
return (ret);
return (ret);
time_rec));
time_rec));