1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* 3 * Copyright (C) 2011-2018 PADL Software Pty Ltd. 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 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 29 * OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "k5-int.h" 33 34 /* 35 * { iso(1) identified-organization(3) dod(6) internet(1) private(4) 36 * enterprise(1) microsoft (311) security(2) mechanisms(2) negoex(30) } 37 */ 38 #define NEGOEX_OID_LENGTH 10 39 #define NEGOEX_OID "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x1e" 40 41 #define MESSAGE_SIGNATURE 0x535458454F47454EULL 42 43 #define EXTENSION_LENGTH 12 44 45 #define EXTENSION_FLAG_CRITICAL 0x80000000 46 47 #define CHECKSUM_SCHEME_RFC3961 1 48 49 #define NEGOEX_KEYUSAGE_INITIATOR_CHECKSUM 23 50 #define NEGOEX_KEYUSAGE_ACCEPTOR_CHECKSUM 25 51 52 #define CHECKSUM_HEADER_LENGTH 20 53 54 #define GUID_LENGTH 16 55 56 typedef uint8_t auth_scheme[GUID_LENGTH]; 57 typedef uint8_t conversation_id[GUID_LENGTH]; 58 #define GUID_EQ(a, b) (memcmp(a, b, GUID_LENGTH) == 0) 59 60 #define NEGO_MESSAGE_HEADER_LENGTH 96 61 #define EXCHANGE_MESSAGE_HEADER_LENGTH 64 62 #define VERIFY_MESSAGE_HEADER_LENGTH 80 63 #define ALERT_MESSAGE_HEADER_LENGTH 72 64 #define ALERT_LENGTH 12 65 #define ALERT_PULSE_LENGTH 8 66 67 #define ALERT_TYPE_PULSE 1 68 #define ALERT_VERIFY_NO_KEY 1 69 70 enum message_type { 71 INITIATOR_NEGO = 0, /* NEGO_MESSAGE */ 72 ACCEPTOR_NEGO, /* NEGO_MESSAGE */ 73 INITIATOR_META_DATA, /* EXCHANGE_MESSAGE */ 74 ACCEPTOR_META_DATA, /* EXCHANGE_MESSAGE */ 75 CHALLENGE, /* EXCHANGE_MESSAGE */ 76 AP_REQUEST, /* EXCHANGE_MESSAGE */ 77 VERIFY, /* VERIFY_MESSAGE */ 78 ALERT, /* ALERT */ 79 }; 80 81 struct nego_message { 82 uint8_t random[32]; 83 const uint8_t *schemes; 84 uint16_t nschemes; 85 }; 86 87 struct exchange_message { 88 auth_scheme scheme; 89 gss_buffer_desc token; 90 }; 91 92 struct verify_message { 93 auth_scheme scheme; 94 uint32_t cksum_type; 95 const uint8_t *cksum; 96 size_t cksum_len; 97 size_t offset_in_token; 98 }; 99 100 struct alert_message { 101 auth_scheme scheme; 102 int verify_no_key; 103 }; 104 105 struct negoex_message { 106 uint32_t type; 107 union { 108 struct nego_message n; 109 struct exchange_message e; 110 struct verify_message v; 111 struct alert_message a; 112 } u; 113 }; 114 115 struct negoex_auth_mech { 116 K5_TAILQ_ENTRY(negoex_auth_mech) links; 117 gss_OID oid; 118 auth_scheme scheme; 119 gss_ctx_id_t mech_context; 120 gss_buffer_desc metadata; 121 krb5_keyblock key; 122 krb5_keyblock verify_key; 123 int complete; 124 int sent_checksum; 125 int verified_checksum; 126 }; 127 128 /* negoex_util.c */ 129 130 OM_uint32 131 negoex_parse_token(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, 132 gss_const_buffer_t token, 133 struct negoex_message **messages_out, size_t *count_out); 134 135 136 struct nego_message * 137 negoex_locate_nego_message(struct negoex_message *messages, size_t nmessages, 138 enum message_type type); 139 struct exchange_message * 140 negoex_locate_exchange_message(struct negoex_message *messages, 141 size_t nmessages, enum message_type type); 142 struct verify_message * 143 negoex_locate_verify_message(struct negoex_message *messages, 144 size_t nmessages); 145 struct alert_message * 146 negoex_locate_alert_message(struct negoex_message *messages, size_t nmessages); 147 148 void 149 negoex_add_nego_message(spnego_gss_ctx_id_t ctx, enum message_type type, 150 uint8_t random[32]); 151 void 152 negoex_add_exchange_message(spnego_gss_ctx_id_t ctx, enum message_type type, 153 const auth_scheme scheme, gss_buffer_t token); 154 void 155 negoex_add_verify_message(spnego_gss_ctx_id_t ctx, const auth_scheme scheme, 156 uint32_t cksum_type, const uint8_t *cksum, 157 uint32_t cksum_len); 158 159 void 160 negoex_add_verify_no_key_alert(spnego_gss_ctx_id_t ctx, 161 const auth_scheme scheme); 162 163 OM_uint32 164 negoex_random(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, 165 unsigned char *data, size_t length); 166 167 void 168 negoex_prep_context_for_spnego(spnego_gss_ctx_id_t ctx); 169 170 OM_uint32 171 negoex_prep_context_for_negoex(OM_uint32 *minor, spnego_gss_ctx_id_t ctx); 172 173 void 174 negoex_release_context(spnego_gss_ctx_id_t ctx); 175 176 OM_uint32 177 negoex_add_auth_mech(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, 178 gss_const_OID oid, auth_scheme scheme); 179 180 void 181 negoex_delete_auth_mech(spnego_gss_ctx_id_t ctx, 182 struct negoex_auth_mech *mech); 183 184 void 185 negoex_select_auth_mech(spnego_gss_ctx_id_t ctx, 186 struct negoex_auth_mech *mech); 187 188 struct negoex_auth_mech * 189 negoex_locate_auth_scheme(spnego_gss_ctx_id_t ctx, const auth_scheme scheme); 190 191 void 192 negoex_common_auth_schemes(spnego_gss_ctx_id_t ctx, 193 const uint8_t *schemes, uint16_t nschemes); 194 195 void 196 negoex_restrict_auth_schemes(spnego_gss_ctx_id_t ctx, 197 const uint8_t *schemes, uint16_t nschemes); 198 199 /* negoex_ctx.c */ 200 201 OM_uint32 202 negoex_init(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, gss_cred_id_t cred, 203 gss_name_t target_name, OM_uint32 req_flags, OM_uint32 time_req, 204 gss_buffer_t input_token, gss_channel_bindings_t bindings, 205 gss_buffer_t output_token, OM_uint32 *time_rec); 206 207 OM_uint32 208 negoex_accept(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, gss_cred_id_t cred, 209 gss_buffer_t input_token, gss_channel_bindings_t bindings, 210 gss_buffer_t output_token, OM_uint32 *time_rec); 211