1/* 2 * Copyright (c) 2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 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 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Portions of this software have been released under the following terms: 31 * 32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC. 33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY 34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION 35 * 36 * To anyone who acknowledges that this file is provided "AS IS" 37 * without any express or implied warranty: 38 * permission to use, copy, modify, and distribute this file for any 39 * purpose is hereby granted without fee, provided that the above 40 * copyright notices and this notice appears in all source code copies, 41 * and that none of the names of Open Software Foundation, Inc., Hewlett- 42 * Packard Company or Digital Equipment Corporation be used 43 * in advertising or publicity pertaining to distribution of the software 44 * without specific, written prior permission. Neither Open Software 45 * Foundation, Inc., Hewlett-Packard Company nor Digital 46 * Equipment Corporation makes any representations about the suitability 47 * of this software for any purpose. 48 * 49 * Copyright (c) 2007, Novell, Inc. All rights reserved. 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 54 * 1. Redistributions of source code must retain the above copyright 55 * notice, this list of conditions and the following disclaimer. 56 * 2. Redistributions in binary form must reproduce the above copyright 57 * notice, this list of conditions and the following disclaimer in the 58 * documentation and/or other materials provided with the distribution. 59 * 3. Neither the name of Novell Inc. nor the names of its contributors 60 * may be used to endorse or promote products derived from this 61 * this software without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY 67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 73 * 74 * @APPLE_LICENSE_HEADER_END@ 75 */ 76 77/* 78** NAME 79** 80** gssauthcn.c 81** 82** FACILITY: 83** 84** Remote Procedure Call (RPC) 85** 86** ABSTRACT: 87** 88** The gssauth CN authentication module. 89** 90** 91*/ 92 93#include <config.h> 94 95#if defined(AUTH_GSS_NEGOTIATE) && AUTH_GSS_NEGOTIATE 96 97#include <gssauth.h> 98#include <gssauthcn.h> 99 100#define RPC__GSSAUTH_CN_AUTH_PADDING 16 101 102INTERNAL boolean32 rpc__gssauth_cn_three_way_winnt (void); /* NTLM only */ 103INTERNAL boolean32 rpc__gssauth_cn_three_way_gss (void); 104 105INTERNAL boolean32 rpc__gssauth_cn_context_valid ( 106 rpc_cn_sec_context_p_t /* in */ /*sec*/, 107 unsigned32 /* out */ * /*st*/ 108 ); 109 110INTERNAL void rpc__gssauth_negotiate_cn_create_info ( 111 rpc_authn_level_t /* in */ /*authn_level*/, 112 rpc_auth_info_p_t /* out */ * /*auth_info*/, 113 unsigned32 /* out */ * /*st*/ 114 ); 115 116INTERNAL void rpc__gssauth_mskrb_cn_create_info ( 117 rpc_authn_level_t /* in */ /*authn_level*/, 118 rpc_auth_info_p_t /* out */ * /*auth_info*/, 119 unsigned32 /* out */ * /*st*/ 120 ); 121 122INTERNAL void rpc__gssauth_winnt_cn_create_info ( 123 rpc_authn_level_t /* in */ /*authn_level*/, 124 rpc_auth_info_p_t /* out */ * /*auth_info*/, 125 unsigned32 /* out */ * /*st*/ 126 ); 127 128INTERNAL void rpc__gssauth_netlogon_cn_create_info ( 129 rpc_authn_level_t /* in */ /*authn_level*/, 130 rpc_auth_info_p_t /* out */ * /*auth_info*/, 131 unsigned32 /* out */ * /*st*/ 132 ); 133INTERNAL boolean32 rpc__gssauth_cn_cred_changed ( 134 rpc_cn_sec_context_p_t /* in */ /*sec*/, 135 unsigned32 /* out */ * /*st*/ 136 ); 137 138INTERNAL void rpc__gssauth_cn_cred_refresh ( 139 rpc_auth_info_p_t /* in */ /*auth_info*/, 140 unsigned32 /* out */ * /*st*/ 141 ); 142 143INTERNAL void rpc__gssauth_cn_fmt_client_req ( 144 rpc_cn_assoc_sec_context_p_t /* in */ /*assoc_sec*/, 145 rpc_cn_sec_context_p_t /* in */ /*sec*/, 146 dce_pointer_t /* in/out */ /*auth_value*/, 147 unsigned32 /* in/out */ * /*auth_value_len*/, 148 dce_pointer_t /* in/out */ * /*last_auth_pos*/, 149 unsigned32 /* out */ * /*auth_len_remain*/, 150 unsigned32 /* in */ /*old_server*/, 151 unsigned32 /* out */ * /*st*/ 152 ); 153 154INTERNAL void rpc__gssauth_cn_fmt_srvr_resp ( 155 unsigned32 /* in */ /*verify_st*/, 156 rpc_cn_assoc_sec_context_p_t /* in */ /*assoc_sec*/, 157 rpc_cn_sec_context_p_t /* in */ /*sec*/, 158 dce_pointer_t /* in */ /*req_auth_value*/, 159 unsigned32 /* in */ /*req_auth_value_len*/, 160 dce_pointer_t /* in/out */ /*auth_value*/, 161 unsigned32 /* in/out */ * /*auth_value_len*/ 162 ); 163 164INTERNAL void rpc__gssauth_cn_free_prot_info ( 165 rpc_auth_info_p_t /* in */ /*info*/, 166 rpc_cn_auth_info_p_t /* in/out */ * /*cn_info*/ 167 ); 168 169INTERNAL void rpc__gssauth_cn_get_prot_info ( 170 rpc_auth_info_p_t /* in */ /*info*/, 171 rpc_cn_auth_info_p_t /* out */ * /*cn_info*/, 172 unsigned32 /* out */ * /*st*/ 173 ); 174 175INTERNAL void rpc__gssauth_cn_pre_call ( 176 rpc_cn_assoc_sec_context_p_t /* in */ /*assoc_sec*/, 177 rpc_cn_sec_context_p_t /* in */ /*sec*/, 178 dce_pointer_t /* in/out */ /*auth_value*/, 179 unsigned32 /* in/out */ * /*auth_value_len*/, 180 unsigned32 /* in/out */ * /*st*/ 181 ); 182 183INTERNAL void rpc__gssauth_cn_pre_send ( 184 rpc_cn_assoc_sec_context_p_t /* in */ /*assoc_sec*/, 185 rpc_cn_sec_context_p_t /* in */ /*sec*/, 186 rpc_socket_iovec_p_t /* in/out */ /*iov*/, 187 unsigned32 /* in */ /*iovlen*/, 188 rpc_socket_iovec_p_t /* out */ /*out_iov*/, 189 unsigned32 /* out */ * /*st*/ 190 ); 191 192INTERNAL void rpc__gssauth_cn_recv_check ( 193 rpc_cn_assoc_sec_context_p_t /* in */ /*assoc_sec*/, 194 rpc_cn_sec_context_p_t /* in */ /*sec*/, 195 rpc_cn_common_hdr_p_t /* in */ /*pdu*/, 196 unsigned32 /* in */ /*pdu_len*/, 197 unsigned32 /* in */ /*cred_len*/, 198 rpc_cn_auth_tlr_p_t /* in */ /*auth_tlr*/, 199 boolean32 /* in */ /*unpack_ints*/, 200 unsigned32 /* out */ * /*st*/ 201 ); 202 203INTERNAL void rpc__gssauth_cn_tlr_uuid_crc ( 204 dce_pointer_t /* in */ /*auth_value*/, 205 unsigned32 /* in */ /*auth_value_len*/, 206 unsigned32 /* out */ * /*uuid_crc*/ 207 ); 208 209INTERNAL void rpc__gssauth_cn_tlr_unpack ( 210 rpc_cn_packet_p_t /* in */ /*pkt_p*/, 211 unsigned32 /* in */ /*auth_value_len*/, 212 unsigned8 /* out */ * /*packed_drep*/ 213 ); 214 215INTERNAL void rpc__gssauth_cn_vfy_client_req ( 216 rpc_cn_assoc_sec_context_p_t /* in */ /*assoc_sec*/, 217 rpc_cn_sec_context_p_t /* in */ /*sec*/, 218 dce_pointer_t /* in */ /*auth_value*/, 219 unsigned32 /* in */ /*auth_value_len*/, 220 unsigned32 /* in */ /*old_client*/, 221 unsigned32 /* out */ * /*st*/ 222 ); 223 224INTERNAL void rpc__gssauth_cn_vfy_srvr_resp ( 225 rpc_cn_assoc_sec_context_p_t /* in */ /*assoc_sec*/, 226 rpc_cn_sec_context_p_t /* in */ /*sec*/, 227 dce_pointer_t /* in/out */ /*auth_value*/, 228 unsigned32 /* in */ /*auth_value_len*/, 229 unsigned32 /* out */ * /*st*/ 230 ); 231 232INTERNAL const rpc_cn_auth_epv_t rpc_g_gssauth_negotiate_cn_epv = 233{ 234 .three_way = rpc__gssauth_cn_three_way_gss, 235 .context_valid = rpc__gssauth_cn_context_valid, 236 .create_info = rpc__gssauth_negotiate_cn_create_info, 237 .cred_changed = rpc__gssauth_cn_cred_changed, 238 .cred_refresh = rpc__gssauth_cn_cred_refresh, 239 .fmt_client_req = rpc__gssauth_cn_fmt_client_req, 240 .fmt_srvr_resp = rpc__gssauth_cn_fmt_srvr_resp, 241 .free_prot_info = rpc__gssauth_cn_free_prot_info, 242 .get_prot_info = rpc__gssauth_cn_get_prot_info, 243 .pre_call = rpc__gssauth_cn_pre_call, 244 .pre_send = rpc__gssauth_cn_pre_send, 245 .recv_check = rpc__gssauth_cn_recv_check, 246 .tlr_uuid_crc = rpc__gssauth_cn_tlr_uuid_crc, 247 .tlr_unpack = rpc__gssauth_cn_tlr_unpack, 248 .vfy_client_req = rpc__gssauth_cn_vfy_client_req, 249 .vfy_srvr_resp = rpc__gssauth_cn_vfy_srvr_resp 250}; 251 252INTERNAL const rpc_cn_auth_epv_t rpc_g_gssauth_mskrb_cn_epv = 253{ 254 .three_way = rpc__gssauth_cn_three_way_gss, 255 .context_valid = rpc__gssauth_cn_context_valid, 256 .create_info = rpc__gssauth_mskrb_cn_create_info, 257 .cred_changed = rpc__gssauth_cn_cred_changed, 258 .cred_refresh = rpc__gssauth_cn_cred_refresh, 259 .fmt_client_req = rpc__gssauth_cn_fmt_client_req, 260 .fmt_srvr_resp = rpc__gssauth_cn_fmt_srvr_resp, 261 .free_prot_info = rpc__gssauth_cn_free_prot_info, 262 .get_prot_info = rpc__gssauth_cn_get_prot_info, 263 .pre_call = rpc__gssauth_cn_pre_call, 264 .pre_send = rpc__gssauth_cn_pre_send, 265 .recv_check = rpc__gssauth_cn_recv_check, 266 .tlr_uuid_crc = rpc__gssauth_cn_tlr_uuid_crc, 267 .tlr_unpack = rpc__gssauth_cn_tlr_unpack, 268 .vfy_client_req = rpc__gssauth_cn_vfy_client_req, 269 .vfy_srvr_resp = rpc__gssauth_cn_vfy_srvr_resp 270}; 271 272INTERNAL const rpc_cn_auth_epv_t rpc_g_gssauth_winnt_cn_epv = 273{ 274 .three_way = rpc__gssauth_cn_three_way_winnt, 275 .context_valid = rpc__gssauth_cn_context_valid, 276 .create_info = rpc__gssauth_winnt_cn_create_info, 277 .cred_changed = rpc__gssauth_cn_cred_changed, 278 .cred_refresh = rpc__gssauth_cn_cred_refresh, 279 .fmt_client_req = rpc__gssauth_cn_fmt_client_req, 280 .fmt_srvr_resp = rpc__gssauth_cn_fmt_srvr_resp, 281 .free_prot_info = rpc__gssauth_cn_free_prot_info, 282 .get_prot_info = rpc__gssauth_cn_get_prot_info, 283 .pre_call = rpc__gssauth_cn_pre_call, 284 .pre_send = rpc__gssauth_cn_pre_send, 285 .recv_check = rpc__gssauth_cn_recv_check, 286 .tlr_uuid_crc = rpc__gssauth_cn_tlr_uuid_crc, 287 .tlr_unpack = rpc__gssauth_cn_tlr_unpack, 288 .vfy_client_req = rpc__gssauth_cn_vfy_client_req, 289 .vfy_srvr_resp = rpc__gssauth_cn_vfy_srvr_resp 290}; 291 292INTERNAL const rpc_cn_auth_epv_t rpc_g_gssauth_netlogon_cn_epv = 293{ 294 .three_way = rpc__gssauth_cn_three_way_gss, 295 .context_valid = rpc__gssauth_cn_context_valid, 296 .create_info = rpc__gssauth_netlogon_cn_create_info, 297 .cred_changed = rpc__gssauth_cn_cred_changed, 298 .cred_refresh = rpc__gssauth_cn_cred_refresh, 299 .fmt_client_req = rpc__gssauth_cn_fmt_client_req, 300 .fmt_srvr_resp = rpc__gssauth_cn_fmt_srvr_resp, 301 .free_prot_info = rpc__gssauth_cn_free_prot_info, 302 .get_prot_info = rpc__gssauth_cn_get_prot_info, 303 .pre_call = rpc__gssauth_cn_pre_call, 304 .pre_send = rpc__gssauth_cn_pre_send, 305 .recv_check = rpc__gssauth_cn_recv_check, 306 .tlr_uuid_crc = rpc__gssauth_cn_tlr_uuid_crc, 307 .tlr_unpack = rpc__gssauth_cn_tlr_unpack, 308 .vfy_client_req = rpc__gssauth_cn_vfy_client_req, 309 .vfy_srvr_resp = rpc__gssauth_cn_vfy_srvr_resp 310}; 311 312/*****************************************************************************/ 313/* 314**++ 315** 316** ROUTINE NAME: rpc__gssauth_cn_three_way 317** 318** SCOPE: INTERNAL - declared locally 319** 320** DESCRIPTION: 321** 322** Determine whether the authentication protocol requires a 323** 3-way authentication handshake. If true the client is expected to 324** provide an rpc_auth3 PDU before the security context is fully 325** established and a call can be made. 326** 327** INPUTS: none 328** 329** INPUTS/OUTPUTS: none 330** 331** OUTPUTS: none 332** 333** IMPLICIT INPUTS: none 334** 335** IMPLICIT OUTPUTS: none 336** 337** FUNCTION VALUE: boolean32 338** 339** True if the authentication protocol requires a 3-way 340** authentication handshake. 341** 342** SIDE EFFECTS: none 343** 344**-- 345**/ 346 347INTERNAL boolean32 rpc__gssauth_cn_three_way_winnt (void) 348{ 349 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 350 ("(rpc__gssauth_cn_three_way)\n")); 351 352 return true; 353} 354 355INTERNAL boolean32 rpc__gssauth_cn_three_way_gss (void) 356{ 357 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 358 ("(rpc__gssauth_cn_three_way)\n")); 359 360 return false; 361} 362 363/*****************************************************************************/ 364/* 365**++ 366** 367** ROUTINE NAME: rpc__gssauth_cn_context_valid 368** 369** SCOPE: INTERNAL - declared locally 370** 371** DESCRIPTION: 372** 373** Determine whether the established security context will be 374** valid (i. e. timely) for the next 300 seconds. If 375** not this routine will try to renew the context. 376** If it cannot be renewed false is returned. This is 377** called from the client side. 378** 379** INPUTS: 380** 381** sec A pointer to security context element which includes 382** the key ID, auth information rep and RPC auth 383** information rep. 384** 385** INPUTS/OUTPUTS: none 386** 387** OUTPUTS: 388** 389** st The return status of this routine. 390** 391** IMPLICIT INPUTS: none 392** 393** IMPLICIT OUTPUTS: none 394** 395** FUNCTION VALUE: boolean32 396** 397** True if security context identified by the auth 398** information rep and RPC auth information rep will 399** still be valid in 300 seconds, false if not. 400** 401** SIDE EFFECTS: 402** 403** The context may be renewed. 404** 405**-- 406**/ 407 408INTERNAL boolean32 rpc__gssauth_cn_context_valid 409( 410 rpc_cn_sec_context_p_t sec, 411 unsigned32 *st 412) 413{ 414 CODING_ERROR (st); 415 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 416 ("(rpc__gssauth_cn_context_valid)\n")); 417 418 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 419 ("(rpc__gssauth_cn_context_valid) prot->%x level->%x key_id->%x\n", 420 sec->sec_info->authn_protocol, 421 sec->sec_info->authn_level, 422 sec->sec_key_id)); 423 424#ifdef DEBUG 425 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_CONTEXT_VALID)) { 426 *st = RPC_S_CN_DBG_AUTH_FAILURE; 427 return false; 428 } 429#endif 430 431 *st = rpc_s_ok; 432 return true; 433} 434 435/*****************************************************************************/ 436/* 437**++ 438** 439** ROUTINE NAME: rpc__gssauth_cn_create_info 440** 441** SCOPE: INTERNAL - declared locally 442** 443** DESCRIPTION: 444** 445** Create an auth information rep data structure with and 446** add a reference to it. This is called on the server 447** side. The fields will be initialized to NULL values. 448** The caller should fill them in based on information 449** decrypted from the authenticator passed in the bind 450** request. 451** 452** INPUTS: 453** 454** authn_level The authentication level to be applied over this 455** security context. 456** 457** INPUTS/OUTPUTS: none 458** 459** OUTPUTS: 460** 461** info A pointer to the auth information rep structure 462** containing RPC protocol indenpendent information. 463** st The return status of this routine. 464** 465** IMPLICIT INPUTS: none 466** 467** IMPLICIT OUTPUTS: none 468** 469** FUNCTION VALUE: none 470** 471** SIDE EFFECTS: 472** 473** The newly create auth info will have a reference count of 1. 474** 475**-- 476**/ 477 478INTERNAL void rpc__gssauth_cn_create_info 479( 480 rpc_authn_protocol_id_t authn_protocol, 481 rpc_authn_level_t authn_level, 482 rpc_auth_info_p_t *auth_info, 483 unsigned32 *st 484) 485{ 486 rpc_gssauth_info_p_t gssauth_info; 487 488 CODING_ERROR(st); 489 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 490 ("(rpc__gssauth_cn_create_info)\n")); 491 492 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 493 ("(rpc__gssauth_cn_create_info) prot->%x level->%x\n", 494 authn_protocol, 495 authn_level)); 496 497#ifdef DEBUG 498 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_CREATE_INFO)) { 499 *st = RPC_S_CN_DBG_AUTH_FAILURE; 500 return; 501 } 502#endif 503 504 switch (authn_level) { 505 case rpc_c_authn_level_connect: 506 case rpc_c_authn_level_pkt_integrity: 507 case rpc_c_authn_level_pkt_privacy: 508 break; 509 default: 510 *st = rpc_s_unsupported_authn_level; 511 return; 512 } 513 514 /* 515 * Allocate storage for a gssauth info structure from heap. 516 */ 517 RPC_MEM_ALLOC(gssauth_info, 518 rpc_gssauth_info_p_t, 519 sizeof (rpc_gssauth_info_t), 520 RPC_C_MEM_GSSAUTH_INFO, 521 RPC_C_MEM_WAITOK); 522 memset (gssauth_info, 0, sizeof(rpc_gssauth_info_t)); 523 524 /* 525 * Initialize the common auth_info stuff. 526 */ 527 gssauth_info->auth_info.refcount = 1; 528 gssauth_info->auth_info.server_princ_name = '\0'; 529 gssauth_info->auth_info.authn_level = authn_level; 530 gssauth_info->auth_info.authn_protocol = authn_protocol; 531 gssauth_info->auth_info.authz_protocol = rpc_c_authz_name; 532 gssauth_info->auth_info.is_server = true; 533 534 *auth_info = &gssauth_info->auth_info; 535 *st = rpc_s_ok; 536} 537 538INTERNAL void rpc__gssauth_negotiate_cn_create_info 539( 540 rpc_authn_level_t authn_level, 541 rpc_auth_info_p_t *auth_info, 542 unsigned32 *st 543) 544{ 545 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 546 ("(rpc__gssauth_negotiate_cn_create_info)\n")); 547 548 rpc__gssauth_cn_create_info(rpc_c_authn_gss_negotiate, 549 authn_level, 550 auth_info, 551 st); 552} 553 554INTERNAL void rpc__gssauth_mskrb_cn_create_info 555( 556 rpc_authn_level_t authn_level, 557 rpc_auth_info_p_t *auth_info, 558 unsigned32 *st 559) 560{ 561 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 562 ("(rpc__gssauth_mskrb_cn_create_info)\n")); 563 564 rpc__gssauth_cn_create_info(rpc_c_authn_gss_mskrb, 565 authn_level, 566 auth_info, 567 st); 568} 569 570INTERNAL void rpc__gssauth_winnt_cn_create_info 571( 572 rpc_authn_level_t authn_level, 573 rpc_auth_info_p_t *auth_info, 574 unsigned32 *st 575) 576{ 577 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 578 ("(rpc__gssauth_winnt_cn_create_info)\n")); 579 580 rpc__gssauth_cn_create_info(rpc_c_authn_winnt, 581 authn_level, 582 auth_info, 583 st); 584} 585 586INTERNAL void rpc__gssauth_netlogon_cn_create_info 587( 588 rpc_authn_level_t authn_level, 589 rpc_auth_info_p_t *auth_info, 590 unsigned32 *st 591) 592{ 593 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 594 ("(rpc__gssauth_netlogon_cn_create_info)\n")); 595 596 rpc__gssauth_cn_create_info(rpc_c_authn_netlogon, 597 authn_level, 598 auth_info, 599 st); 600} 601 602/*****************************************************************************/ 603/* 604**++ 605** 606** ROUTINE NAME: rpc__gssauth_cn_cred_changed 607** 608** SCOPE: INTERNAL - declared locally 609** 610** DESCRIPTION: 611** 612** Determine whether the client's credentials stored in the 613** security context are different from those in the auth info. 614** If they are not the same return true, else false. 615** 616** INPUTS: 617** 618** sec A pointer to security context element which includes 619** the key ID, auth information rep and RPC auth 620** information rep. 621** 622** INPUTS/OUTPUTS: none 623** 624** OUTPUTS: 625** 626** st The return status of this routine. 627** 628** IMPLICIT INPUTS: none 629** 630** IMPLICIT OUTPUTS: none 631** 632** FUNCTION VALUE: boolean32 633** 634** True if the credentials identified by the auth 635** information rep and RPC auth information rep are different, 636** false if not. 637** 638** The md5 checksum algorithm requires the use of the session key 639** to encrypt the CRC(assoc_uuid). Since the session key will 640** change when the credential changes, this routine sets the flag 641** indicating that a (potentially) valid encrypted crc is now 642** invalid, forcing a recomputation. 643** 644** SIDE EFFECTS: none 645** 646**-- 647**/ 648 649INTERNAL boolean32 rpc__gssauth_cn_cred_changed 650( 651 rpc_cn_sec_context_p_t sec, 652 unsigned32 *st 653) 654{ 655 CODING_ERROR(st); 656 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 657 ("(rpc__gssauth_cn_cred_changed)\n")); 658 659 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 660 ("(rpc__gssauth_cn_cred_changed) prot->%x level->%x key_id->%x\n", 661 sec->sec_info->authn_protocol, 662 sec->sec_info->authn_level, 663 sec->sec_key_id)); 664 665#ifdef DEBUG 666 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_CRED_CHANGED)) { 667 *st = RPC_S_CN_DBG_AUTH_FAILURE; 668 return false; 669 } 670#endif 671 672 /* 673 * Assume that cred is already valid. 674 */ 675 *st = rpc_s_ok; 676 return false; 677} 678 679/*****************************************************************************/ 680/* 681**++ 682** 683** ROUTINE NAME: rpc__gssauth_cn_cred_refresh 684** 685** SCOPE: INTERNAL - declared locally 686** 687** DESCRIPTION: 688** 689** Determine whether the client's credentials are still 690** valid. If not this routine will try to renew the credentials. 691** If they cannot be renewed an error is returned. This routine 692** is called from the client side. 693** 694** INPUTS: 695** 696** auth_info A pointer to the auth information rep 697** 698** INPUTS/OUTPUTS: none 699** 700** OUTPUTS: 701** 702** st The return status of this routine. 703** 704** IMPLICIT INPUTS: none 705** 706** IMPLICIT OUTPUTS: none 707** 708** FUNCTION VALUE: none 709** 710** SIDE EFFECTS: none 711** 712**-- 713**/ 714 715INTERNAL void rpc__gssauth_cn_cred_refresh 716( 717 rpc_auth_info_p_t auth_info, 718 unsigned32 *st 719) 720{ 721 CODING_ERROR(st); 722 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 723 ("(rpc__gssauth_cn_cred_refresh)\n")); 724 725 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 726 ("(rpc__gssauth_cn_cred_refresh) prot->%x level->%x\n", 727 auth_info->authn_protocol, 728 auth_info->authn_level)); 729 730#ifdef DEBUG 731 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_CRED_REFRESH)) { 732 *st = RPC_S_CN_DBG_AUTH_FAILURE; 733 return; 734 } 735#endif 736 737 /* 738 * Assume that cred is already valid. 739 */ 740 *st = rpc_s_ok; 741} 742 743PRIVATE const char *rpc__gssauth_error_map 744( 745 OM_uint32 maj_stat, 746 OM_uint32 min_stat, 747 const gss_OID mech, 748 char *message_buffer, 749 unsigned32 message_length, 750 unsigned32 *st 751) 752{ 753 switch (maj_stat) { 754 case GSS_S_BAD_MECH: 755 *st = rpc_s_unknown_authn_service; 756 break; 757 case GSS_S_BAD_NAME: 758 *st = rpc_s_unsupported_name_syntax; 759 break; 760 case GSS_S_BAD_BINDINGS: 761 *st = rpc_s_auth_badaddr; 762 break; 763 case GSS_S_BAD_STATUS: 764 *st = rpc_s_unknown_status_code; 765 break; 766 case GSS_S_BAD_SIG: 767 *st = rpc_s_auth_bad_integrity; 768 break; 769 case GSS_S_NO_CRED: 770 case GSS_S_NO_CONTEXT: 771 *st = rpc_s_auth_nokey; 772 break; 773 case GSS_S_DEFECTIVE_TOKEN: 774 *st = rpc_s_auth_field_toolong; 775 break; 776 case GSS_S_DEFECTIVE_CREDENTIAL: 777 *st = rpc_s_invalid_credentials; 778 break; 779 case GSS_S_CONTEXT_EXPIRED: 780 *st = rpc_s_auth_tkt_expired; 781 break; 782 case GSS_S_BAD_QOP: 783 *st = rpc_s_protect_level_mismatch; 784 break; 785 case GSS_S_UNAUTHORIZED: 786 *st = rpc_s_authn_authz_mismatch; 787 break; 788 case GSS_S_NAME_NOT_MN: 789 *st = rpc_s_auth_not_us; 790 break; 791 case GSS_S_OLD_TOKEN: 792 case GSS_S_DUPLICATE_TOKEN: 793 *st = rpc_s_auth_repeat; 794 break; 795 case GSS_S_GAP_TOKEN: 796 *st = rpc_s_auth_badorder; 797 break; 798 case GSS_S_UNSEQ_TOKEN: 799 *st = rpc_s_auth_badseq; 800 break; 801 case GSS_S_CONTINUE_NEEDED: 802 *st = rpc_s_partial_credentials; 803 break; 804 case GSS_S_COMPLETE: 805 *st = rpc_s_ok; 806 break; 807 case GSS_S_DUPLICATE_ELEMENT: 808 case GSS_S_UNAVAILABLE: 809 case GSS_S_FAILURE: 810 default: 811 *st = rpc_s_auth_method; 812 break; 813 } 814 815 /* 816 * Possibly this should check that mech is GSS_KRB5_MECHANISM first. 817 * But, it's likely that other mechanisms use the krb5 minor status 818 * namespace too, and/or that the Kerberos mechanism uses a different 819 * OID. So safest to leave it as is for now. 820 */ 821 switch ((signed32) min_stat) { 822 case KRB5KRB_AP_ERR_BAD_INTEGRITY: 823 *st = rpc_s_auth_bad_integrity; 824 break; 825 case KRB5KRB_AP_ERR_TKT_EXPIRED: 826 *st = rpc_s_auth_tkt_expired; 827 break; 828 case KRB5KRB_AP_ERR_TKT_NYV: 829 *st = rpc_s_auth_tkt_nyv; 830 break; 831 case KRB5KRB_AP_ERR_REPEAT: 832 *st = rpc_s_auth_repeat; 833 break; 834 case KRB5KRB_AP_ERR_NOT_US: 835 *st = rpc_s_auth_not_us; 836 break; 837 case KRB5KRB_AP_ERR_BADMATCH: 838 *st = rpc_s_auth_badmatch; 839 break; 840 case KRB5KRB_AP_ERR_SKEW: 841 *st = rpc_s_auth_skew; 842 break; 843 case KRB5KRB_AP_ERR_BADADDR: 844 *st = rpc_s_auth_badaddr; 845 break; 846 case KRB5KRB_AP_ERR_BADVERSION: 847 *st = rpc_s_auth_badversion; 848 break; 849 case KRB5KRB_AP_ERR_MSG_TYPE: 850 *st = rpc_s_auth_msg_type; 851 break; 852 case KRB5KRB_AP_ERR_MODIFIED: 853 *st = rpc_s_auth_modified; 854 break; 855 case KRB5KRB_AP_ERR_BADORDER: 856 *st = rpc_s_auth_badorder; 857 break; 858 case KRB5KRB_AP_ERR_BADKEYVER: 859 *st = rpc_s_auth_badkeyver; 860 break; 861 case KRB5KRB_AP_ERR_NOKEY: 862 *st = rpc_s_auth_nokey; 863 break; 864 case KRB5KRB_AP_ERR_MUT_FAIL: 865 *st = rpc_s_auth_mut_fail; 866 break; 867 case KRB5KRB_AP_ERR_BADDIRECTION: 868 *st = rpc_s_auth_baddirection; 869 break; 870 case KRB5KRB_AP_ERR_METHOD: 871 *st = rpc_s_auth_method; 872 break; 873 case KRB5KRB_AP_ERR_BADSEQ: 874 *st = rpc_s_auth_badseq; 875 break; 876 case KRB5KRB_AP_ERR_INAPP_CKSUM: 877 *st = rpc_s_auth_inapp_cksum; 878 break; 879 default: 880 break; 881 } 882 883 if (message_buffer != NULL && message_length != 0) { 884 OM_uint32 min2; 885 gss_buffer_desc major_msg; 886 gss_buffer_desc minor_msg; 887 OM_uint32 msg_ctx = 0; 888 889 major_msg.value = NULL; 890 major_msg.length = 0; 891 minor_msg.value = NULL; 892 minor_msg.length = 0; 893 894 gss_display_status(&min2, maj_stat, GSS_C_GSS_CODE, 895 NULL, &msg_ctx, &major_msg); 896 gss_display_status(&min2, min_stat, GSS_C_MECH_CODE, 897 mech, &msg_ctx, &minor_msg); 898 899 snprintf((char *)message_buffer, message_length - 1, 900 "major: %*s (%u) minor: %*s (%u) => dcerpc: (0x%08x)\n", 901 (int)major_msg.length, (char *)major_msg.value, 902 maj_stat, (int)minor_msg.length, 903 (char *)minor_msg.value, min_stat, 904 (unsigned int)*st); 905 message_buffer[message_length - 1] = '\0'; 906 907 gss_release_buffer(&min2, &major_msg); 908 gss_release_buffer(&min2, &minor_msg); 909 910 return (const char *)message_buffer; 911 } 912 913 return NULL; 914} 915 916INTERNAL OM_uint32 rpc__gssauth_select_flags 917( 918 OM_uint32 *min_stat, 919 rpc_authn_level_t authn_level, 920 OM_uint32 *req_flags 921) 922{ 923 OM_uint32 flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | 924 GSS_C_SEQUENCE_FLAG | GSS_C_DCE_STYLE; 925 *min_stat = 0; 926 927 switch (authn_level) { 928 case rpc_c_authn_level_connect: 929 break; 930 case rpc_c_protect_level_pkt_integ: 931 flags |= GSS_C_INTEG_FLAG; 932 break; 933 case rpc_c_protect_level_pkt_privacy: 934 flags |= GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG; 935 break; 936 } 937 938 *req_flags = flags; 939 return GSS_S_COMPLETE; 940} 941 942INTERNAL OM_uint32 rpc__gssauth_create_client_token 943( 944 OM_uint32 *min_stat, 945 const rpc_cn_sec_context_p_t sec, 946 const gss_cred_id_t gss_creds, 947 const gss_name_t gss_server_name, 948 gss_ctx_id_t *gss_ctx, 949 gss_OID *actual_mech, 950 gss_buffer_desc *output_token 951) 952{ 953 OM_uint32 maj_stat; 954 gss_OID req_mech = GSS_C_NO_OID; 955 OM_uint32 req_flags; 956 gss_buffer_desc input_token; 957 958 maj_stat = rpc__gssauth_select_mech(min_stat, 959 sec->sec_info->authn_protocol, 960 &req_mech); 961 if (maj_stat != GSS_S_COMPLETE) { 962 return maj_stat; 963 } 964 965 maj_stat = rpc__gssauth_select_flags(min_stat, 966 sec->sec_info->authn_level, 967 &req_flags); 968 if (maj_stat != GSS_S_COMPLETE) { 969 return maj_stat; 970 } 971 972 input_token.value = NULL; 973 input_token.length = 0; 974 975 maj_stat = gss_init_sec_context(min_stat, 976 gss_creds, 977 gss_ctx, 978 gss_server_name, 979 req_mech, 980 req_flags, 981 GSS_C_INDEFINITE, 982 NULL, 983 &input_token, 984 actual_mech, 985 output_token, 986 NULL, 987 NULL); 988 return maj_stat; 989} 990 991INTERNAL OM_uint32 rpc__gssauth_verify_server_token 992( 993 OM_uint32 *min_stat, 994 const rpc_cn_sec_context_p_t sec, 995 const gss_cred_id_t gss_creds, 996 const gss_name_t gss_server_name, 997 gss_ctx_id_t gss_ctx, 998 gss_buffer_desc input_token, 999 gss_OID *actual_mech, 1000 gss_buffer_desc *output_token 1001) 1002{ 1003 OM_uint32 maj_stat; 1004 gss_OID req_mech = GSS_C_NO_OID; 1005 OM_uint32 req_flags; 1006 1007 assert(gss_ctx != GSS_C_NO_CONTEXT); 1008 1009 maj_stat = rpc__gssauth_select_mech(min_stat, 1010 sec->sec_info->authn_protocol, 1011 &req_mech); 1012 if (maj_stat != GSS_S_COMPLETE) { 1013 return maj_stat; 1014 } 1015 1016 maj_stat = rpc__gssauth_select_flags(min_stat, 1017 sec->sec_info->authn_protocol, 1018 &req_flags); 1019 if (maj_stat != GSS_S_COMPLETE) { 1020 return maj_stat; 1021 } 1022 1023 maj_stat = gss_init_sec_context(min_stat, 1024 gss_creds, 1025 &gss_ctx, 1026 gss_server_name, 1027 req_mech, 1028 req_flags, 1029 GSS_C_INDEFINITE, 1030 NULL, 1031 &input_token, 1032 actual_mech, 1033 output_token, 1034 NULL, 1035 NULL); 1036 1037 return maj_stat; 1038} 1039 1040/*****************************************************************************/ 1041/* 1042**++ 1043** 1044** ROUTINE NAME: rpc__gssauth_cn_fmt_client_req 1045** 1046** SCOPE: INTERNAL - declared locally 1047** 1048** DESCRIPTION: 1049** 1050** This routine will format the auth_value field of 1051** either an rpc_bind or rpc_alter_context PDU. This is 1052** called from the client side association state machine. 1053** 1054** INPUTS: 1055** 1056** assoc_sec A pointer to per-association security context 1057** including association UUID CRC and sequence numbers. 1058** sec A pointer to security context element which includes 1059** the key ID, auth information rep and RPC auth 1060** information rep. 1061** auth_value A pointer to the auth_value field in the rpc_bind or 1062** rpc_alter_context PDU authentication trailer. 1063** 1064** INPUTS/OUTPUTS: 1065** 1066** auth_value_len On input, the lenght, in bytes of the available space 1067** for the auth_value field. On output, the lenght in 1068** bytes used in encoding the auth_value field. Zero if 1069** an error status is returned. 1070** 1071** OUTPUTS: 1072** 1073** st The return status of this routine. 1074** 1075** IMPLICIT INPUTS: none 1076** 1077** IMPLICIT OUTPUTS: none 1078** 1079** FUNCTION VALUE: none 1080** 1081** SIDE EFFECTS: none 1082** 1083**-- 1084**/ 1085 1086INTERNAL void rpc__gssauth_cn_fmt_client_req 1087( 1088 rpc_cn_assoc_sec_context_p_t assoc_sec ATTRIBUTE_UNUSED, 1089 rpc_cn_sec_context_p_t sec, 1090 dce_pointer_t auth_value, 1091 unsigned32 *auth_value_len, 1092 dce_pointer_t *last_auth_pos ATTRIBUTE_UNUSED, 1093 unsigned32 *auth_len_remain, 1094 unsigned32 old_server ATTRIBUTE_UNUSED, 1095 unsigned32 *st 1096) 1097{ 1098 rpc_gssauth_info_p_t gssauth_info = (rpc_gssauth_info_p_t)sec->sec_info; 1099 rpc_gssauth_cn_info_p_t gssauth_cn_info = (rpc_gssauth_cn_info_p_t)sec->sec_cn_info; 1100 int maj_stat; 1101 OM_uint32 min_stat; 1102 gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; 1103 1104 CODING_ERROR(st); 1105 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 1106 ("(rpc__gssauth_cn_fmt_client_req)\n")); 1107 1108 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 1109 ("(rpc__gssauth_cn_fmt_client_req) prot->%x level->%x key_id->%x assoc_uuid_crc->%x xmit_seq->%x recv_seq->%x\n", 1110 sec->sec_info->authn_protocol, 1111 sec->sec_info->authn_level, 1112 sec->sec_key_id, 1113 assoc_sec->assoc_uuid_crc, 1114 assoc_sec->assoc_next_snd_seq, 1115 assoc_sec->assoc_next_rcv_seq)); 1116 1117#ifdef DEBUG 1118 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_FMT_CLIENT_REQ)) { 1119 *st = RPC_S_CN_DBG_AUTH_FAILURE; 1120 return; 1121 } 1122#endif 1123 1124 if (gssauth_cn_info->gss_ctx != GSS_C_NO_CONTEXT) { 1125 /* 1126 * transfer the output of rpc__gssauth_verify_server_token() 1127 */ 1128 output_token.length = assoc_sec->krb_message.length; 1129 output_token.value = assoc_sec->krb_message.data; 1130 assoc_sec->krb_message.length = 0; 1131 assoc_sec->krb_message.data = NULL; 1132 } else { 1133 maj_stat = rpc__gssauth_create_client_token(&min_stat, 1134 sec, 1135 gssauth_info->gss_creds, 1136 gssauth_info->gss_server_name, 1137 &gssauth_cn_info->gss_ctx, 1138 &gssauth_cn_info->gss_mech, 1139 &output_token); 1140 if (GSS_ERROR(maj_stat)) { 1141 char msg[BUFSIZ]; 1142 rpc__gssauth_error_map(maj_stat, min_stat, 1143 gssauth_cn_info->gss_mech, 1144 msg, sizeof(msg), st); 1145 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL, 1146 ("(rpc__gssauth_cn_fmt_client_req): %s\n", msg)); 1147 return; 1148 } 1149 gssauth_cn_info->gss_stat = maj_stat; 1150 } 1151 1152 if (*auth_value_len < output_token.length) { 1153 assoc_sec->krb_message.length = (int) output_token.length; 1154 assoc_sec->krb_message.data = output_token.value; 1155 1156 *auth_value_len = (unsigned32) output_token.length; 1157 memset((unsigned_char_p_t)auth_value, 0xAF, *auth_value_len); 1158 } else { 1159 *auth_value_len = (unsigned32) output_token.length; 1160 *auth_len_remain = 0; 1161 1162 memcpy((unsigned_char_p_t)auth_value, 1163 output_token.value, 1164 output_token.length); 1165 1166 gss_release_buffer(&min_stat, &output_token); 1167 } 1168 1169 *st = rpc_s_ok; 1170} 1171 1172/*****************************************************************************/ 1173/* 1174**++ 1175** 1176** ROUTINE NAME: rpc__gssauth_cn_fmt_srvr_resp 1177** 1178** SCOPE: INTERNAL - declared locally 1179** 1180** DESCRIPTION: 1181** 1182** This routine will format the auth_value field of 1183** either an rpc_bind_ack or rpc_alter_context_response 1184** PDU. The authentication protocol encoding in the 1185** credentials field of auth_value should correspond 1186** to the status returned from rpc__auth_cn_vfy_ 1187** client_req() routine. This credentials field, when 1188** decoded by rpc__auth_cn_vfy_srvr_resp(), should 1189** result in the same error code being returned. If the 1190** memory provided is not large enough an authentication 1191** protocol specific error message will be encoded in 1192** the credentials field indicating this error. This is 1193** called from the server side association state machine. 1194** 1195** INPUTS: 1196** 1197** verify_st The status code returned by rpc__auth_cn_verify_ 1198** client_req(). 1199** assoc_sec A pointer to per-association security context 1200** including association UUID CRC and sequence numbers. 1201** sec A pointer to security context element which includes 1202** the key ID, auth information rep and RPC auth 1203** information rep. 1204** req_auth_value A pointer to the auth_value field in the 1205** rpc_bind or rpc_alter_context PDU authentication trailer. 1206** req_auth_value_len The length, in bytes, of the 1207** req_auth_value field. 1208** auth_value A pointer to the auth_value field in the rpc_bind or 1209** rpc_alter_context PDU authentication trailer. 1210** 1211** INPUTS/OUTPUTS: 1212** 1213** auth_value_len On input, the length, in bytes of the available space 1214** for the auth_value field. On output, the length in 1215** bytes used in encoding the auth_value field. Zero if 1216** an error status is returned. 1217** 1218** OUTPUTS: none 1219** 1220** IMPLICIT INPUTS: none 1221** 1222** IMPLICIT OUTPUTS: none 1223** 1224** FUNCTION VALUE: none 1225** 1226** SIDE EFFECTS: none 1227** 1228**-- 1229**/ 1230 1231INTERNAL void rpc__gssauth_cn_fmt_srvr_resp 1232( 1233 unsigned32 verify_st, 1234 rpc_cn_assoc_sec_context_p_t assoc_sec, 1235 rpc_cn_sec_context_p_t sec, 1236 dce_pointer_t req_auth_value ATTRIBUTE_UNUSED /*TODO*/, 1237 unsigned32 req_auth_value_len ATTRIBUTE_UNUSED /*TODO*/, 1238 dce_pointer_t auth_value, 1239 unsigned32 *auth_value_len 1240) 1241{ 1242 OM_uint32 min_stat; 1243 gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; 1244 1245 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 1246 ("(rpc__gssauth_cn_fmt_srvr_resp)\n")); 1247 1248 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 1249 ("(rpc__gssauth_cn_fmt_srvr_resp) prot->%x level->%x key_id->%x assoc_uuid_crc->%x xmit_seq->%x recv_seq->%x, vfy_client_st->%x\n", 1250 sec->sec_info->authn_protocol, 1251 sec->sec_info->authn_level, 1252 sec->sec_key_id, 1253 assoc_sec->assoc_uuid_crc, 1254 assoc_sec->assoc_next_snd_seq, 1255 assoc_sec->assoc_next_rcv_seq, 1256 verify_st)); 1257 1258#if 0 1259 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_FMT_SERVER_RESP)) { 1260 verify_st = RPC_S_CN_DBG_AUTH_FAILURE; 1261 } 1262#endif 1263 1264 /* 1265 * transfer the output of rpc__gssauth_cn_vfy_client_req() 1266 */ 1267 output_token.length = assoc_sec->krb_message.length; 1268 output_token.value = assoc_sec->krb_message.data; 1269 assoc_sec->krb_message.length = 0; 1270 assoc_sec->krb_message.data = NULL; 1271 1272 if (*auth_value_len < output_token.length) { 1273 gss_release_buffer(&min_stat, &output_token); 1274 *auth_value_len = 0; 1275 return; 1276 } 1277 1278 *auth_value_len = (unsigned32) output_token.length; 1279 1280 memcpy((unsigned_char_p_t)auth_value, 1281 output_token.value, 1282 output_token.length); 1283 1284 gss_release_buffer(&min_stat, &output_token); 1285} 1286 1287/*****************************************************************************/ 1288/* 1289**++ 1290** 1291** ROUTINE NAME: rpc__gssauth_cn_free_prot_info 1292** 1293** SCOPE: INTERNAL - declared locally 1294** 1295** DESCRIPTION: 1296** 1297** This routine will free an NCA Connection RPC auth 1298** information rep. 1299** 1300** INPUTS: 1301** 1302** info A pointer to the auth information rep structure 1303** containing RPC protocol indenpendent information. 1304** 1305** INPUTS/OUTPUTS: 1306** 1307** cn_info A pointer to the RPC auth information rep structure 1308** containing NCA Connection specific 1309** information. NULL on output. 1310** 1311** OUTPUTS: none 1312** 1313** IMPLICIT INPUTS: none 1314** 1315** IMPLICIT OUTPUTS: none 1316** 1317** FUNCTION VALUE: none 1318** 1319** SIDE EFFECTS: none 1320** 1321**-- 1322**/ 1323 1324INTERNAL void rpc__gssauth_cn_free_prot_info 1325( 1326 rpc_auth_info_p_t info, 1327 rpc_cn_auth_info_p_t *cn_info 1328) 1329{ 1330 rpc_gssauth_cn_info_p_t gssauth_cn_info = (rpc_gssauth_cn_info_p_t)*cn_info; 1331 OM_uint32 min_stat; 1332 1333 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 1334 ("(rpc__gssauth_cn_free_prot_info)\n")); 1335 1336 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 1337 ("(rpc__gssauth_cn_free_prot_info) prot->%x level->%x \n", 1338 info->authn_protocol, 1339 info->authn_level)); 1340 1341 if (gssauth_cn_info->gss_ctx != GSS_C_NO_CONTEXT) { 1342 gss_delete_sec_context(&min_stat, 1343 &gssauth_cn_info->gss_ctx, 1344 GSS_C_NO_BUFFER); 1345 gssauth_cn_info->gss_ctx = GSS_C_NO_CONTEXT; 1346 } 1347 1348#ifdef DEBUG 1349 memset (gssauth_cn_info, 0, sizeof (rpc_gssauth_cn_info_p_t)); 1350#endif 1351 1352 RPC_MEM_FREE (gssauth_cn_info, RPC_C_MEM_GSSAUTH_CN_INFO); 1353 *cn_info = NULL; 1354} 1355 1356/*****************************************************************************/ 1357/* 1358**++ 1359** 1360** ROUTINE NAME: rpc__gssauth_cn_get_prot_info 1361** 1362** SCOPE: INTERNAL - declared locally 1363** 1364** DESCRIPTION: 1365** 1366** This routine will create and return an NCA Connection 1367** RPC auth information rep. 1368** 1369** INPUTS: 1370** 1371** info A pointer to the auth information rep structure 1372** containing RPC protocol indenpendent information. 1373** 1374** INPUTS/OUTPUTS: none 1375** 1376** OUTPUTS: 1377** 1378** cn_info A pointer to the RPC auth information rep structure 1379** containing NCA Connection specific information. 1380** st The return status of this routine. 1381** 1382** IMPLICIT INPUTS: none 1383** 1384** IMPLICIT OUTPUTS: none 1385** 1386** FUNCTION VALUE: none 1387** 1388** SIDE EFFECTS: none 1389** 1390**-- 1391**/ 1392 1393INTERNAL void rpc__gssauth_cn_get_prot_info 1394( 1395 rpc_auth_info_p_t info, 1396 rpc_cn_auth_info_p_t *cn_info, 1397 unsigned32 *st 1398) 1399{ 1400 rpc_gssauth_cn_info_t *gssauth_cn_info = NULL; 1401 rpc_gssauth_info_t *gssauth_info = (rpc_gssauth_info_p_t)info; 1402 1403 CODING_ERROR(st); 1404 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 1405 ("(rpc__gssauth_cn_get_prot_info)\n")); 1406 1407 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 1408 ("(rpc__gssauth_cn_get_prot_info) prot->%x level->%x \n", 1409 info->authn_protocol, 1410 info->authn_level)); 1411 1412#ifdef DEBUG 1413 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_GET_PROT_INFO)) { 1414 *st = RPC_S_CN_DBG_AUTH_FAILURE; 1415 return; 1416 } 1417#endif 1418 1419 /* 1420 * Allocate storage for a gssauth cn info structure from heap. 1421 */ 1422 RPC_MEM_ALLOC(gssauth_cn_info, 1423 rpc_gssauth_cn_info_p_t, 1424 sizeof (rpc_gssauth_cn_info_t), 1425 RPC_C_MEM_GSSAUTH_CN_INFO, 1426 RPC_C_MEM_WAITOK); 1427 1428 /* 1429 * Initialize it. 1430 */ 1431 memset (gssauth_cn_info, 0, sizeof(rpc_gssauth_cn_info_t)); 1432 1433 /* 1434 * Set pointer to connection specific auth info if we're 1435 * on the server side. 1436 */ 1437 if (info->is_server) { 1438 gssauth_info->cn_info = gssauth_cn_info; 1439 } 1440 1441 *cn_info = &gssauth_cn_info->cn_info; 1442 *st = rpc_s_ok; 1443} 1444 1445/*****************************************************************************/ 1446/* 1447**++ 1448** 1449** ROUTINE NAME: rpc__gssauth_cn_pre_call 1450** 1451** SCOPE: INTERNAL - declared locally 1452** 1453** DESCRIPTION: 1454** 1455** This routine will format the auth_value field of 1456** a call level PDU, namely an rpc_request, rpc_response 1457** rpc_fault, rpc_remote_alert or rpc_orphaned PDU. It will 1458** also format the auth_value field of the association level 1459** rpc_shutdown PDU. This does 1460** not include generating any checksums in the auth_value_field 1461** or encrypting of data corresponding to the authentication 1462** level. That will be done in the rpc__cn_auth_pre_send 1463** routine. This is called on both client and server when a the 1464** data structures and header template for a call is being set up. 1465** 1466** INPUTS: 1467** 1468** assoc_sec A pointer to per-association security context 1469** including association UUID CRC and sequence numbers. 1470** sec A pointer to security context element which includes 1471** the key ID, auth information rep and RPC auth 1472** information rep. 1473** auth_value A pointer to the auth_value field in the rpc_bind or 1474** rpc_alter_context PDU authentication trailer. 1475** 1476** INPUTS/OUTPUTS: 1477** 1478** auth_value_len On input, the lenght, in bytes of the available space 1479** for the auth_value field. On output, the lenght in 1480** bytes used in encoding the auth_value field. Zero if 1481** an error status is returned. 1482** 1483** OUTPUTS: 1484** 1485** st The return status of this routine. 1486** 1487** IMPLICIT INPUTS: none 1488** 1489** IMPLICIT OUTPUTS: none 1490** 1491** FUNCTION VALUE: none 1492** 1493** SIDE EFFECTS: none 1494** 1495**-- 1496**/ 1497 1498INTERNAL void rpc__gssauth_cn_pre_call 1499( 1500 rpc_cn_assoc_sec_context_p_t assoc_sec, 1501 rpc_cn_sec_context_p_t sec, 1502 dce_pointer_t auth_value, 1503 unsigned32 *auth_value_len, 1504 unsigned32 *st 1505) 1506{ 1507 rpc_gssauth_cn_info_p_t gssauth_cn_info = (rpc_gssauth_cn_info_p_t)sec->sec_cn_info; 1508 OM_uint32 maj_stat; 1509 OM_uint32 min_stat; 1510 gss_iov_buffer_desc iov[2]; 1511 int conf_req_flag = 0; 1512 1513 CODING_ERROR(st); 1514 1515 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 1516 ("(rpc__gssauth_cn_pre_call)\n")); 1517 1518 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 1519 ("(rpc__gssauth_cn_pre_call) prot->%x level->%x key_id->%x assoc_uuid_crc->%x xmit_seq->%x recv_seq->%x\n", 1520 sec->sec_info->authn_protocol, 1521 sec->sec_info->authn_level, 1522 sec->sec_key_id, 1523 assoc_sec->assoc_uuid_crc, 1524 assoc_sec->assoc_next_snd_seq, 1525 assoc_sec->assoc_next_rcv_seq)); 1526 1527#ifdef DEBUG 1528 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_PRE_CALL)) { 1529 *st = RPC_S_CN_DBG_AUTH_FAILURE; 1530 return; 1531 } 1532#endif 1533 1534 if (gssauth_cn_info->gss_stat != GSS_S_COMPLETE) { 1535 /* Can only do this on a completed context */ 1536 *st = rpc_s_ok; 1537 return; 1538 } 1539 1540 switch (sec->sec_info->authn_level) { 1541 case rpc_c_protect_level_pkt_privacy: 1542 conf_req_flag = 1; 1543 /* fallthrough */ 1544 case rpc_c_protect_level_pkt_integ: 1545 iov[0].type = GSS_IOV_BUFFER_TYPE_DATA; 1546 iov[0].buffer.length = RPC__GSSAUTH_CN_AUTH_PADDING; 1547 1548 iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER; 1549 iov[1].buffer.length = 0; 1550 1551 /* 1552 * XXX needs to report correct Get_MIC token size too 1553 * Correctness of this relies on MIC tokens always being 1554 * equal to or smaller than wrap tokens. 1555 */ 1556 maj_stat = gss_wrap_iov_length(&min_stat, 1557 gssauth_cn_info->gss_ctx, 1558 conf_req_flag, 1559 GSS_C_QOP_DEFAULT, 1560 NULL, /* conf_state */ 1561 iov, 1562 sizeof(iov)/sizeof(iov[0])); 1563 if (maj_stat != GSS_S_COMPLETE) { 1564 *st = rpc_s_auth_method; 1565 return; 1566 } 1567 *auth_value_len = (unsigned32) iov[1].buffer.length; 1568 memset((unsigned_char_p_t)auth_value, 0xAF, *auth_value_len); 1569 break; 1570 case rpc_c_authn_level_connect: 1571 default: 1572 *auth_value_len = 0; 1573 break; 1574 } 1575 1576 *st = rpc_s_ok; 1577} 1578 1579INTERNAL void rpc__gssauth_cn_wrap_packet 1580( 1581 rpc_cn_sec_context_p_t sec, 1582 const char *comment, 1583 unsigned8 header_size, 1584 rpc_socket_iovec_p_t iov, 1585 unsigned32 iovlen, 1586 boolean conf_req_flag, 1587 rpc_socket_iovec_p_t out_iov, 1588 unsigned32 *st 1589) 1590{ 1591 rpc_gssauth_cn_info_p_t gssauth_cn_info = (rpc_gssauth_cn_info_p_t)sec->sec_cn_info; 1592 rpc_cn_common_hdr_p_t pdu; 1593 rpc_cn_auth_tlr_p_t auth_tlr; 1594 unsigned32 i; 1595 unsigned8 pad_len; 1596 OM_uint32 maj_stat; 1597 OM_uint32 min_stat; 1598 int conf_state; 1599 gss_iov_buffer_desc gss_iov[4]; 1600 unsigned_char_p_t pdu_buf; 1601 size_t pdu_buflen, payload_len; 1602 boolean header_sign = gssauth_cn_info->header_sign; 1603 1604 CODING_ERROR(st); 1605 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 1606 ("(rpc__gssauth_cn_wrap_packet)\n")); 1607 1608 if (iovlen < 2) { 1609 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL, 1610 ("(rpc__gssauth_cn_wrap_packet): %s: iovlen[%u]\n", 1611 comment, (unsigned int)iovlen)); 1612 *st = rpc_m_no_stub_data; 1613 return; 1614 } 1615 if (iov[0].iov_len < header_size) { 1616 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL, 1617 ("(rpc__gssauth_cn_wrap_packet): %s: iov[0].iov_len[%u] < header_size[%u]\n", 1618 comment, (unsigned int)iov[0].iov_len,(unsigned int)header_size)); 1619 *st = rpc_m_no_stub_data; 1620 return; 1621 } 1622 if (iov[iovlen - 1].iov_len < RPC_CN_PKT_SIZEOF_COM_AUTH_TLR) { 1623 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL, 1624 ("(rpc__gssauth_cn_wrap_packet): %s: iov[%u].iov_len[%u] != %u\n", 1625 comment,(unsigned int)iovlen - 1, 1626 (unsigned int)iov[iovlen - 1].iov_len, 1627 RPC_CN_PKT_SIZEOF_COM_AUTH_TLR)); 1628 *st = rpc_s_auth_field_toolong; 1629 return; 1630 } 1631 1632 for (i = 0, payload_len = 0; i < iovlen - 1; i++) { 1633 payload_len += iov[i].iov_len; 1634 } 1635 1636 /* 1637 * [MS-RPCE] states that the stub data is padded to the underlying 1638 * blocksize (or four bytes, if that is greater). In practice they 1639 * use the underlying keysize when the blocksize is one. For now, 1640 * a constant 16 bytes works for all known ciphers and mechanisms 1641 * (at the expense of 8 bytes extra padding for DES), but we should 1642 * eventually fix it to use gss_context_query_attributes(). 1643 */ 1644 payload_len -= header_size; 1645 pad_len = RPC__GSSAUTH_CN_AUTH_PADDING - 1646 (payload_len % RPC__GSSAUTH_CN_AUTH_PADDING); 1647 if (pad_len == RPC__GSSAUTH_CN_AUTH_PADDING) 1648 pad_len = 0; 1649 1650 pdu_buflen = header_size + payload_len + pad_len + iov[iovlen - 1].iov_len; 1651 1652 RPC_MEM_ALLOC(pdu_buf, 1653 unsigned_char_p_t, 1654 pdu_buflen, 1655 RPC_C_MEM_CN_ENCRYPT_BUF, 1656 RPC_C_MEM_WAITOK); 1657 memset(pdu_buf, 0xAF, pdu_buflen); 1658 1659 pdu = (rpc_cn_common_hdr_p_t)pdu_buf; 1660 1661 for (i = 0, pdu_buflen = 0; i < iovlen - 1; i++) { 1662 memcpy(&pdu_buf[pdu_buflen], 1663 iov[i].iov_base, 1664 iov[i].iov_len); 1665 pdu_buflen += iov[i].iov_len; 1666 } 1667 1668 memset(&pdu_buf[pdu_buflen], 0, pad_len); 1669 1670 gss_iov[0].type = header_sign ? GSS_IOV_BUFFER_TYPE_SIGN_ONLY : 1671 GSS_IOV_BUFFER_TYPE_EMPTY; 1672 gss_iov[0].buffer.value = pdu_buf; 1673 gss_iov[0].buffer.length = header_size; 1674 1675 gss_iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; 1676 gss_iov[1].buffer.value = (unsigned_char_p_t)gss_iov[0].buffer.value + 1677 gss_iov[0].buffer.length; 1678 gss_iov[1].buffer.length = payload_len + pad_len; 1679 1680 gss_iov[2].type = header_sign ? GSS_IOV_BUFFER_TYPE_SIGN_ONLY : 1681 GSS_IOV_BUFFER_TYPE_EMPTY; 1682 gss_iov[2].buffer.value = (unsigned_char_p_t)gss_iov[1].buffer.value + 1683 gss_iov[1].buffer.length; 1684 gss_iov[2].buffer.length = RPC_CN_PKT_SIZEOF_COM_AUTH_TLR; 1685 1686 /* 1687 * The auth trailer may have moved relative to the start of the PDU 1688 * owing to any additional padding. Really, we should be able to allocate 1689 * just a padding [out] IOV and do the rest in place. This would require 1690 * some rejigging of the auth provider interface. 1691 */ 1692 memcpy(gss_iov[2].buffer.value, iov[iovlen - 1].iov_base, gss_iov[2].buffer.length); 1693 1694 auth_tlr = (rpc_cn_auth_tlr_p_t)gss_iov[2].buffer.value; 1695 auth_tlr->stub_pad_length = pad_len; 1696 1697 gss_iov[3].type = GSS_IOV_BUFFER_TYPE_HEADER; 1698 gss_iov[3].buffer.value = (unsigned_char_p_t)gss_iov[2].buffer.value + 1699 gss_iov[2].buffer.length; 1700 gss_iov[3].buffer.length = iov[iovlen - 1].iov_len - RPC_CN_PKT_SIZEOF_COM_AUTH_TLR; 1701 1702 pdu->frag_len = gss_iov[0].buffer.length + 1703 gss_iov[1].buffer.length + 1704 gss_iov[2].buffer.length + 1705 gss_iov[3].buffer.length; 1706 1707 pdu->auth_len = gss_iov[3].buffer.length; 1708 1709 if (conf_req_flag) { 1710 maj_stat = gss_wrap_iov(&min_stat, 1711 gssauth_cn_info->gss_ctx, 1712 conf_req_flag, 1713 GSS_C_QOP_DEFAULT, 1714 &conf_state, 1715 gss_iov, 1716 sizeof(gss_iov)/sizeof(gss_iov[0])); 1717 if (maj_stat != GSS_S_COMPLETE) 1718 goto cleanup; 1719 } else { 1720 gss_buffer_desc input_token; 1721 gss_buffer_desc mic_token; 1722 1723 conf_state = 0; 1724 1725 if (header_sign) { 1726 input_token = gss_iov[0].buffer; 1727 input_token.length += gss_iov[1].buffer.length + gss_iov[2].buffer.length; 1728 } else { 1729 input_token = gss_iov[1].buffer; 1730 } 1731 1732 maj_stat = gss_get_mic(&min_stat, 1733 gssauth_cn_info->gss_ctx, 1734 GSS_C_QOP_DEFAULT, 1735 &input_token, 1736 &mic_token); 1737 if (maj_stat != GSS_S_COMPLETE) 1738 goto cleanup; 1739 1740 assert(mic_token.length <= gss_iov[3].buffer.length); 1741 memcpy(gss_iov[3].buffer.value, mic_token.value, mic_token.length); 1742 gss_iov[3].buffer.length = mic_token.length; 1743 gss_release_buffer(&min_stat, &mic_token); 1744 } 1745 1746 if (conf_req_flag != conf_state) { 1747 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL, 1748 ("(rpc__gssauth_cn_wrap_packet): %s: conf_req[%u] != conf_state[%u]\n", 1749 comment, (unsigned int)conf_req_flag, (unsigned int)conf_state)); 1750 *st = rpc_s_auth_method; 1751 goto cleanup; 1752 } 1753 1754 out_iov->iov_base = pdu_buf; 1755 out_iov->iov_len = pdu->frag_len; 1756 1757 *st = rpc_s_ok; 1758 1759cleanup: 1760 if (maj_stat != GSS_S_COMPLETE) { 1761 char msg[BUFSIZ]; 1762 rpc__gssauth_error_map(maj_stat, min_stat, 1763 gssauth_cn_info->gss_mech, 1764 msg, sizeof(msg), st); 1765 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL, 1766 ("(rpc__gssauth_cn_wrap_packet): %s: %s\n", comment, msg)); 1767 } 1768 1769 return; 1770} 1771 1772INTERNAL void rpc__gssauth_cn_create_large_frag 1773( 1774 rpc_cn_assoc_sec_context_p_t assoc_sec, 1775 const char *comment, 1776 unsigned8 header_size, 1777 rpc_socket_iovec_p_t iov, 1778 unsigned32 iovlen, 1779 rpc_socket_iovec_p_t out_iov, 1780 unsigned32 *st 1781) 1782{ 1783 rpc_cn_common_hdr_p_t pdu; 1784 unsigned32 i; 1785 unsigned32 pdu_buflen; 1786 unsigned_char_p_t pdu_buf, pdu_bufp; 1787 OM_uint32 min_stat; 1788 gss_buffer_desc output_token; 1789 1790 CODING_ERROR(st); 1791 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 1792 ("(rpc__gssauth_cn_create_large_frag)\n")); 1793 1794 output_token.length = assoc_sec->krb_message.length; 1795 output_token.value = assoc_sec->krb_message.data; 1796 assoc_sec->krb_message.length = 0; 1797 assoc_sec->krb_message.data = NULL; 1798 1799 if (iovlen < 1) { 1800 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL, 1801 ("(rpc__gssauth_cn_create_large_frag): %s: iovlen[%u]\n", 1802 comment, (unsigned int)iovlen)); 1803 gss_release_buffer(&min_stat, &output_token); 1804 *st = rpc_m_no_stub_data; 1805 return; 1806 } 1807 if (iov[0].iov_len < header_size) { 1808 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL, 1809 ("(rpc__gssauth_cn_create_large_frag): %s: iov[0].iov_len[%u] < header_size[%u]\n", 1810 comment, (unsigned int)iov[0].iov_len,(unsigned int)header_size)); 1811 gss_release_buffer(&min_stat, &output_token); 1812 *st = rpc_m_no_stub_data; 1813 return; 1814 } 1815 1816 for (i = 0, pdu_buflen = 0; i < iovlen; i++) { 1817 pdu_buflen += iov[i].iov_len; 1818 } 1819 1820 if (pdu_buflen < header_size + RPC_CN_PKT_SIZEOF_COM_AUTH_TLR + output_token.length) { 1821 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL, 1822 ("(rpc__gssauth_cn_create_large_frag): %s: pdu_buflen[%u] < min_len[%u]\n", 1823 comment, (unsigned int)pdu_buflen, 1824 (unsigned int)header_size + 1825 RPC_CN_PKT_SIZEOF_COM_AUTH_TLR + (unsigned int)output_token.length)); 1826 gss_release_buffer(&min_stat, &output_token); 1827 *st = rpc_m_no_stub_data; 1828 return; 1829 } 1830 1831 pdu_buflen += output_token.length; 1832 1833 RPC_MEM_ALLOC(pdu_buf, 1834 unsigned_char_p_t, 1835 pdu_buflen, 1836 RPC_C_MEM_CN_ENCRYPT_BUF, 1837 RPC_C_MEM_WAITOK); 1838 1839 pdu_bufp = pdu_buf; 1840 pdu = (rpc_cn_common_hdr_p_t)pdu_bufp; 1841 for (i = 0; i < iovlen; i++) { 1842 memcpy(pdu_bufp, iov[i].iov_base, iov[i].iov_len); 1843 pdu_bufp += iov[i].iov_len; 1844 } 1845 1846 memcpy(pdu_bufp, output_token.value, output_token.length); 1847 pdu_bufp += output_token.length; 1848 1849 pdu->frag_len = (pdu_bufp - pdu_buf); 1850 pdu->auth_len = output_token.length; 1851 1852 out_iov->iov_base = pdu_buf; 1853 out_iov->iov_len = pdu_buflen; 1854 1855 assert(out_iov->iov_len == pdu->frag_len); 1856 1857 gss_release_buffer(&min_stat, &output_token); 1858 1859 *st = rpc_s_ok; 1860} 1861 1862/*****************************************************************************/ 1863/* 1864**++ 1865** 1866** ROUTINE NAME: rpc__gssauth_cn_pre_send 1867** 1868** SCOPE: INTERNAL - declared locally 1869** 1870** DESCRIPTION: 1871** 1872** This routine will perform per-packet security 1873** processing on a packet before it is sent. This 1874** includes checksumming and encryption. 1875** 1876** Note that in some cases, the data is copied to 1877** a contiguous buffer for checksumming and 1878** encryption. In these cases, the contiguous 1879** iov element should be used instead of the original 1880** iovector. 1881** 1882** INPUTS: 1883** 1884** assoc_sec A pointer to per-association security context 1885** including association UUID CRC and sequence numbers. 1886** sec A pointer to security context element which includes 1887** the key ID, auth information rep and RPC auth 1888** information rep. 1889** iov A pointer to the iovector containing the PDU 1890** about to be sent. The appropriate per-packet security 1891** services will be applied to it. 1892** iovlen The length, in bytes, of the PDU. 1893** out_iov An iovector element. This iovector element 1894** will describe packet if the original iov 1895** had to be copied. If the original iov was 1896** copied, out_iov->iov_base will be non-NULL. 1897** 1898** INPUTS/OUTPUTS: none 1899** 1900** OUTPUTS: 1901** 1902** st The return status of this routine. 1903** 1904** IMPLICIT INPUTS: none 1905** 1906** IMPLICIT OUTPUTS: none 1907** 1908** FUNCTION VALUE: none 1909** 1910** SIDE EFFECTS: none 1911** 1912**-- 1913**/ 1914 1915INTERNAL void rpc__gssauth_cn_pre_send 1916( 1917 rpc_cn_assoc_sec_context_p_t assoc_sec, 1918 rpc_cn_sec_context_p_t sec, 1919 rpc_socket_iovec_p_t iov, 1920 unsigned32 iovlen, 1921 rpc_socket_iovec_p_t out_iov, 1922 unsigned32 *st 1923) 1924{ 1925 rpc_gssauth_cn_info_p_t gssauth_cn_info = (rpc_gssauth_cn_info_p_t)sec->sec_cn_info; 1926 rpc_cn_common_hdr_p_t pdu; 1927 rpc_cn_packet_p_t pkt; 1928 unsigned32 ptype; 1929 boolean conf_req_flag = false; 1930 OM_uint32 min_stat; 1931 1932 CODING_ERROR(st); 1933 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 1934 ("(rpc__gssauth_cn_pre_send)\n")); 1935 1936 pdu = (rpc_cn_common_hdr_p_t)iov[0].iov_base; 1937 pkt = (rpc_cn_packet_p_t)pdu; 1938 ptype = pdu->ptype; 1939 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL, 1940 ("(rpc__gssauth_cn_pre_send) authn level->%x packet type->%x\n", 1941 sec->sec_info->authn_level, ptype)); 1942 1943 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 1944 ("(rpc__gssauth_cn_pre_send) prot->%x level->%x key_id->%x assoc_uuid_crc->%x xmit_seq->%x recv_seq->%x ptype->%x\n", 1945 sec->sec_info->authn_protocol, 1946 sec->sec_info->authn_level, 1947 sec->sec_key_id, 1948 assoc_sec->assoc_uuid_crc, 1949 assoc_sec->assoc_next_snd_seq, 1950 assoc_sec->assoc_next_rcv_seq, 1951 ptype)); 1952 1953#ifdef DEBUG 1954 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_PRE_SEND)) { 1955 *st = RPC_S_CN_DBG_AUTH_FAILURE; 1956 return; 1957 } 1958#endif 1959 1960 out_iov->iov_base = NULL; 1961 1962 switch (ptype) { 1963 case RPC_C_CN_PKT_REQUEST: 1964 case RPC_C_CN_PKT_RESPONSE: 1965 switch (sec->sec_info->authn_level) { 1966 case rpc_c_authn_level_connect: 1967 *st = rpc_s_ok; 1968 break; 1969 case rpc_c_authn_level_pkt_privacy: 1970 conf_req_flag = true; 1971 /* fallthrough */ 1972 case rpc_c_authn_level_pkt_integrity: 1973 rpc__gssauth_cn_wrap_packet(sec, 1974 ptype == RPC_C_CN_PKT_REQUEST ? "request" : "response", 1975 ptype == RPC_C_CN_PKT_REQUEST ? RPC_CN_PKT_SIZEOF_RQST_HDR : 1976 RPC_CN_PKT_SIZEOF_RESP_HDR, 1977 iov, iovlen, conf_req_flag, out_iov, st); 1978 break; 1979 default: 1980 break; 1981 } 1982 break; 1983 case RPC_C_CN_PKT_BIND: 1984 case RPC_C_CN_PKT_ALTER_CONTEXT: 1985 if (!getenv("DCE_DISABLE_HEADER_SIGN")) { 1986 RPC_CN_PKT_FLAGS(pkt) |= RPC_C_CN_FLAGS_SUPPORT_HEADER_SIGN; 1987 } 1988 if (assoc_sec->krb_message.length == 0) { 1989 *st = rpc_s_ok; 1990 } else { 1991 rpc__gssauth_cn_create_large_frag(assoc_sec, 1992 (ptype == RPC_C_CN_PKT_BIND) ? "bind" : "alter_context", 1993 RPC_CN_PKT_SIZEOF_BIND_HDR, 1994 iov, iovlen, out_iov, st); 1995 } 1996 break; 1997 case RPC_C_CN_PKT_BIND_ACK: 1998 case RPC_C_CN_PKT_BIND_NAK: 1999 case RPC_C_CN_PKT_ALTER_CONTEXT_RESP: 2000 if (gssauth_cn_info->header_sign) 2001 RPC_CN_PKT_FLAGS(pkt) |= RPC_C_CN_FLAGS_SUPPORT_HEADER_SIGN; 2002 break; 2003 case RPC_C_CN_PKT_AUTH3: { 2004 gss_buffer_desc input_token, output_token; 2005 rpc_cn_auth_tlr_p_t auth_tlr; 2006 2007 if (sec->sec_info->is_server) 2008 break; 2009 2010 assert(iovlen == 1); 2011 2012 auth_tlr = RPC_CN_PKT_AUTH_TLR(pkt, iov[0].iov_len); 2013 input_token.value = auth_tlr->auth_value; 2014 input_token.length = RPC_CN_PKT_AUTH_LEN(pkt); 2015 2016 (void) rpc__gssauth_verify_server_token(&min_stat, 2017 sec, 2018 GSS_C_NO_CREDENTIAL, 2019 GSS_C_NO_NAME, 2020 gssauth_cn_info->gss_ctx, 2021 input_token, 2022 &gssauth_cn_info->gss_mech, 2023 &output_token); 2024 if (output_token.length) { 2025 *st = rpc_s_credentials_too_large; 2026 gss_release_buffer(&min_stat, &output_token); 2027 return; 2028 } 2029 break; 2030 } 2031 case RPC_C_CN_PKT_FAULT: 2032 case RPC_C_CN_PKT_SHUTDOWN: 2033 case RPC_C_CN_PKT_REMOTE_ALERT: 2034 case RPC_C_CN_PKT_ORPHANED: 2035 default: 2036 break; 2037 } 2038} 2039 2040INTERNAL void rpc__gssauth_cn_unwrap_packet 2041( 2042 rpc_cn_sec_context_p_t sec, 2043 const char *comment, 2044 unsigned8 header_size, 2045 rpc_cn_common_hdr_p_t pdu, 2046 unsigned32 pdu_len, 2047 unsigned32 cred_len ATTRIBUTE_UNUSED, 2048 rpc_cn_auth_tlr_p_t auth_tlr, 2049 boolean conf_req_flag, 2050 boolean32 unpack_ints, 2051 unsigned32 *st 2052) 2053{ 2054 rpc_gssauth_cn_info_p_t gssauth_cn_info = (rpc_gssauth_cn_info_p_t)sec->sec_cn_info; 2055 OM_uint32 maj_stat; 2056 OM_uint32 min_stat; 2057 int conf_state; 2058 gss_qop_t qop_state; 2059 unsigned16 auth_len; 2060 gss_iov_buffer_desc gss_iov[4]; 2061 boolean header_sign = gssauth_cn_info->header_sign; 2062 2063 CODING_ERROR(st); 2064 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 2065 ("(rpc__gssauth_cn_unwrap_packet)\n")); 2066 2067 auth_len = pdu->auth_len; 2068 if (unpack_ints) { 2069 SWAB_INPLACE_16(auth_len); 2070 } 2071 2072 gss_iov[0].type = header_sign ? GSS_IOV_BUFFER_TYPE_SIGN_ONLY : 2073 GSS_IOV_BUFFER_TYPE_EMPTY; 2074 gss_iov[0].buffer.value = (unsigned_char_p_t)pdu; 2075 gss_iov[0].buffer.length = header_size; 2076 2077 gss_iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; 2078 gss_iov[1].buffer.value = (unsigned_char_p_t)pdu + header_size; 2079 gss_iov[1].buffer.length = pdu_len - 2080 (header_size + RPC_CN_PKT_SIZEOF_COM_AUTH_TLR + auth_len); 2081 2082 gss_iov[2].type = header_sign ? GSS_IOV_BUFFER_TYPE_SIGN_ONLY : 2083 GSS_IOV_BUFFER_TYPE_EMPTY; 2084 gss_iov[2].buffer.value = auth_tlr; 2085 gss_iov[2].buffer.length = RPC_CN_PKT_SIZEOF_COM_AUTH_TLR; 2086 2087 gss_iov[3].type = GSS_IOV_BUFFER_TYPE_HEADER; 2088 gss_iov[3].buffer.value = (unsigned_char_p_t)auth_tlr + 2089 RPC_CN_PKT_SIZEOF_COM_AUTH_TLR; 2090 gss_iov[3].buffer.length = auth_len; 2091 2092 if (conf_req_flag) { 2093 maj_stat = gss_unwrap_iov(&min_stat, 2094 gssauth_cn_info->gss_ctx, 2095 &conf_state, 2096 &qop_state, 2097 gss_iov, 2098 sizeof(gss_iov)/sizeof(gss_iov[0])); 2099 } else { 2100 gss_buffer_desc input_token; 2101 2102 conf_state = 0; 2103 2104 if (header_sign) { 2105 input_token = gss_iov[0].buffer; 2106 input_token.length += gss_iov[1].buffer.length + gss_iov[2].buffer.length; 2107 } else { 2108 input_token = gss_iov[1].buffer; 2109 } 2110 2111 maj_stat = gss_verify_mic(&min_stat, 2112 gssauth_cn_info->gss_ctx, 2113 &input_token, 2114 &gss_iov[3].buffer, 2115 &qop_state); 2116 } 2117 2118 if (maj_stat != GSS_S_COMPLETE) { 2119 char msg[BUFSIZ]; 2120 rpc__gssauth_error_map(maj_stat, min_stat, 2121 gssauth_cn_info->gss_mech, 2122 msg, sizeof(msg), st); 2123 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL, 2124 ("(rpc__gssauth_cn_unwrap_packet): %s: %s\n", 2125 comment, msg)); 2126 /* *st is already filled */ 2127 } else if (conf_state != conf_req_flag) { 2128 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL, 2129 ("(rpc__gssauth_cn_unwrap_packet): %s: packet privacy mismatch\n", 2130 comment)); 2131 *st = rpc_s_auth_bad_integrity; 2132 } else { 2133 *st = rpc_s_ok; 2134 } 2135 2136 return; 2137} 2138 2139/*****************************************************************************/ 2140/* 2141**++ 2142** 2143** ROUTINE NAME: rpc__gssauth_cn_recv_check 2144** 2145** SCOPE: INTERNAL - declared locally 2146** 2147** DESCRIPTION: 2148** 2149** This routine will perform per-packet security 2150** processing on a packet after it is received. This 2151** includes decryption and verification of checksums. 2152** 2153** INPUTS: 2154** 2155** assoc_sec A pointer to per-association security context 2156** including association UUID CRC and sequence numbers. 2157** sec A pointer to security context element which includes 2158** the key ID, auth information rep and RPC auth 2159** information rep. 2160** pdu A pointer to the PDU about to be sent. The appropriate 2161** per-packet security services will be applied to it. 2162** pdu_len The length, in bytes, of the PDU. 2163** cred_len The length, in bytes, of the credentials. 2164** auth_tlr A pointer to the auth trailer. 2165** unpack_ints A boolean indicating whether the integer rep 2166** of fields in the pdu need to be adjusted for 2167** endian differences. 2168** 2169** INPUTS/OUTPUTS: none 2170** 2171** OUTPUTS: 2172** 2173** st The return status of this routine. 2174** 2175** IMPLICIT INPUTS: none 2176** 2177** IMPLICIT OUTPUTS: none 2178** 2179** FUNCTION VALUE: none 2180** 2181** SIDE EFFECTS: none 2182** 2183**-- 2184**/ 2185 2186INTERNAL void rpc__gssauth_cn_recv_check 2187( 2188 rpc_cn_assoc_sec_context_p_t assoc_sec, 2189 rpc_cn_sec_context_p_t sec, 2190 rpc_cn_common_hdr_p_t pdu, 2191 unsigned32 pdu_len, 2192 unsigned32 cred_len, 2193 rpc_cn_auth_tlr_p_t auth_tlr, 2194 boolean32 unpack_ints, 2195 unsigned32 *st 2196) 2197{ 2198 rpc_gssauth_cn_info_p_t gssauth_cn_info = (rpc_gssauth_cn_info_p_t)sec->sec_cn_info; 2199 boolean conf_req_flag = false; 2200 rpc_cn_packet_p_t pkt = (rpc_cn_packet_p_t)pdu; 2201 2202 CODING_ERROR(st); 2203 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 2204 ("(rpc__gssauth_cn_recv_check)\n")); 2205 2206 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL, 2207 ("(rpc__gssauth_cn_recv_check) authn level->%x packet type->%x\n", 2208 sec->sec_info->authn_level, 2209 pdu->ptype)); 2210 2211 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 2212 ("(rpc__gssauth_cn_recv_check) prot->%x level->%x key_id->%x assoc_uuid_crc->%x xmit_seq->%x recv_seq->%x ptype->%x\n", 2213 sec->sec_info->authn_protocol, 2214 sec->sec_info->authn_level, 2215 sec->sec_key_id, 2216 assoc_sec->assoc_uuid_crc, 2217 assoc_sec->assoc_next_snd_seq, 2218 assoc_sec->assoc_next_rcv_seq, 2219 pdu->ptype)); 2220 2221#ifdef DEBUG 2222 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_RECV_CHECK)) { 2223 *st = RPC_S_CN_DBG_AUTH_FAILURE; 2224 return; 2225 } 2226#endif 2227 2228 switch (pdu->ptype) { 2229 case RPC_C_CN_PKT_REQUEST: 2230 case RPC_C_CN_PKT_RESPONSE: 2231 switch (sec->sec_info->authn_level) { 2232 case rpc_c_authn_level_connect: 2233 *st = rpc_s_ok; 2234 break; 2235 case rpc_c_authn_level_pkt_privacy: 2236 conf_req_flag = true; 2237 /* fallthrough */ 2238 case rpc_c_authn_level_pkt_integrity: 2239 rpc__gssauth_cn_unwrap_packet(sec, 2240 (pdu->ptype == RPC_C_CN_PKT_REQUEST) ? "request" : "response", 2241 (pdu->ptype == RPC_C_CN_PKT_REQUEST) ? RPC_CN_PKT_SIZEOF_RQST_HDR : RPC_CN_PKT_SIZEOF_RESP_HDR, 2242 pdu, pdu_len, cred_len, auth_tlr, conf_req_flag, 2243 unpack_ints, st); 2244 break; 2245 } 2246 break; 2247 case RPC_C_CN_PKT_AUTH3: 2248 case RPC_C_CN_PKT_BIND: 2249 case RPC_C_CN_PKT_BIND_ACK: 2250 case RPC_C_CN_PKT_BIND_NAK: 2251 case RPC_C_CN_PKT_ALTER_CONTEXT: 2252 case RPC_C_CN_PKT_ALTER_CONTEXT_RESP: 2253 if (RPC_CN_PKT_FLAGS(pkt) & RPC_C_CN_FLAGS_SUPPORT_HEADER_SIGN) 2254 gssauth_cn_info->header_sign = true; 2255 /* fallthrough */ 2256 case RPC_C_CN_PKT_SHUTDOWN: 2257 case RPC_C_CN_PKT_REMOTE_ALERT: 2258 case RPC_C_CN_PKT_ORPHANED: 2259 case RPC_C_CN_PKT_FAULT: 2260 default: 2261 *st = rpc_s_ok; 2262 break; 2263 } 2264} 2265 2266/*****************************************************************************/ 2267/* 2268**++ 2269** 2270** ROUTINE NAME: rpc__gssauth_cn_tlr_uuid_crc 2271** 2272** SCOPE: INTERNAL - declared locally 2273** 2274** DESCRIPTION: 2275** 2276** This routine will locate and return the association 2277** UUID CRC contained in the auth_value field of an 2278** authentication trailer of an rpc_bind, rpc_bind_ack, 2279** rpc_alter_context or rpc_alter_context_response PDU. 2280** 2281** INPUTS: 2282** 2283** auth_value A pointer to the auth_value field in an authentication 2284** trailer. 2285** auth_value_len The length, in bytes, of the auth_value field. 2286** 2287** INPUTS/OUTPUTS: none 2288** 2289** OUTPUTS: 2290** 2291** assoc_uuid_crc The association UUID CRC contained in the auth_value 2292** field. 2293** 2294** IMPLICIT INPUTS: none 2295** 2296** IMPLICIT OUTPUTS: none 2297** 2298** FUNCTION VALUE: none 2299** 2300** SIDE EFFECTS: none 2301** 2302**-- 2303**/ 2304 2305INTERNAL void rpc__gssauth_cn_tlr_uuid_crc 2306( 2307 dce_pointer_t auth_value ATTRIBUTE_UNUSED /*TODO*/, 2308 unsigned32 auth_value_len ATTRIBUTE_UNUSED /*TODO*/, 2309 unsigned32 *uuid_crc 2310) 2311{ 2312 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 2313 ("(rpc__gssauth_cn_tlr_uuid_crc)\n")); 2314 2315 *uuid_crc = 0; 2316 2317 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL, 2318 ("(rpc__gssauth_cn_tlr_uuid_crc) assoc_uuid_crc->%x\n", *uuid_crc)); 2319} 2320 2321/*****************************************************************************/ 2322/* 2323**++ 2324** 2325** ROUTINE NAME: rpc__gssauth_cn_tlr_unpack 2326** 2327** SCOPE: INTERNAL - declared locally 2328** 2329** DESCRIPTION: 2330** 2331** This routine will byte swap all the appropriate fields 2332** of the the auth_value field of an authentication 2333** trailer. It will also convert any characters from 2334** the remote representation into the local, for example, 2335** ASCII to EBCDIC. 2336** 2337** INPUTS: 2338** 2339** auth_value_len The length, in bytes, of the auth_value field. 2340** packed_drep The packed Networ Data Representation, (see NCA RPC 2341** RunTime Extensions Specification Version OSF TX1.0.9 2342** pre 1003 for details), of the remote machine. 2343** 2344** INPUTS/OUTPUTS: 2345** 2346** pkt_p A pointer to the entire packet. 2347** 2348** OUTPUTS: none 2349** 2350** IMPLICIT INPUTS: none 2351** 2352** IMPLICIT OUTPUTS: none 2353** 2354** FUNCTION VALUE: none 2355** 2356** SIDE EFFECTS: none 2357** 2358**-- 2359**/ 2360 2361INTERNAL void rpc__gssauth_cn_tlr_unpack 2362( 2363 rpc_cn_packet_p_t pkt_p ATTRIBUTE_UNUSED /*TODO*/, 2364 unsigned32 auth_value_len ATTRIBUTE_UNUSED /*TODO*/, 2365 unsigned8 *packed_drep ATTRIBUTE_UNUSED /*TODO*/ 2366) 2367{ 2368 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 2369 ("(rpc__gssauth_cn_tlr_unpack)\n")); 2370} 2371 2372/*****************************************************************************/ 2373/* 2374**++ 2375** 2376** ROUTINE NAME: rpc__gssauth_cn_vfy_client_req 2377** 2378** SCOPE: INTERNAL - declared locally 2379** 2380** DESCRIPTION: 2381** 2382** This routine will decode the auth_value field of 2383** either an rpc_bind or rpc_alter_context PDU. Any 2384** error encountered while authenticating the client 2385** will result in an error status return. The contents 2386** of the credentials field includes the authorization 2387** data. This is called from the server side association 2388** state machine. Note that upon successful return 2389** the auth information rep will contain the client's 2390** authorization protocol and data. 2391** 2392** INPUTS: 2393** 2394** assoc_sec A pointer to per-association security context 2395** including association UUID CRC and sequence numbers. 2396** sec A pointer to security context element which includes 2397** the key ID, auth information rep and RPC auth 2398** information rep. 2399** auth_value A pointer to the auth_value field in the rpc_bind or 2400** rpc_alter_context PDU authentication trailer. 2401** auth_value_len The length, in bytes, of auth_value. 2402** 2403** INPUTS/OUTPUTS: none 2404** 2405** OUTPUTS: 2406** 2407** st The return status of this routine. 2408** 2409** IMPLICIT INPUTS: none 2410** 2411** IMPLICIT OUTPUTS: none 2412** 2413** FUNCTION VALUE: none 2414** 2415** SIDE EFFECTS: none 2416** 2417**-- 2418**/ 2419 2420INTERNAL void rpc__gssauth_cn_vfy_client_req 2421( 2422 rpc_cn_assoc_sec_context_p_t assoc_sec, 2423 rpc_cn_sec_context_p_t sec, 2424 dce_pointer_t auth_value, 2425 unsigned32 auth_value_len, 2426 unsigned32 old_client ATTRIBUTE_UNUSED /*TODO*/, 2427 unsigned32 *st 2428) 2429{ 2430 rpc_gssauth_cn_info_p_t gssauth_cn_info = (rpc_gssauth_cn_info_p_t)sec->sec_cn_info; 2431 int maj_stat; 2432 OM_uint32 min_stat = 0; 2433 gss_buffer_desc input_token, output_token = GSS_C_EMPTY_BUFFER; 2434 2435 CODING_ERROR(st); 2436 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 2437 ("(rpc__gssauth_cn_vfy_client_req)\n")); 2438 2439 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 2440 ("(rpc__gssauth_cn_vfy_client_req) prot->%x level->%x key_id->%x assoc_uuid_crc->%x xmit_seq->%x recv_seq->%x\n", 2441 sec->sec_info->authn_protocol, 2442 sec->sec_info->authn_level, 2443 sec->sec_key_id, 2444 assoc_sec->assoc_uuid_crc, 2445 assoc_sec->assoc_next_snd_seq, 2446 assoc_sec->assoc_next_rcv_seq)); 2447 2448#ifdef DEBUG 2449 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_VFY_CLIENT_REQ)) { 2450 *st = RPC_S_CN_DBG_AUTH_FAILURE; 2451 return; 2452 } 2453#endif 2454 2455 input_token.value = auth_value; 2456 input_token.length = auth_value_len; 2457 2458 maj_stat = gss_accept_sec_context(&min_stat, 2459 &gssauth_cn_info->gss_ctx, 2460 NULL, 2461 &input_token, 2462 NULL, 2463 NULL, 2464 &gssauth_cn_info->gss_mech, 2465 &output_token, 2466 NULL, 2467 NULL, 2468 NULL); 2469 gssauth_cn_info->gss_stat = maj_stat; 2470 if (maj_stat == GSS_S_CONTINUE_NEEDED) { 2471 char msg[BUFSIZ]; 2472 rpc__gssauth_error_map(maj_stat, min_stat, 2473 gssauth_cn_info->gss_mech, 2474 msg, sizeof(msg), st); 2475 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL, 2476 ("(rpc__gssauth_cn_vfy_client_req): %s: output_token.length[%u]\n", 2477 msg, (unsigned int)output_token.length)); 2478 /* 2479 * we still transfer the buffer to the client 2480 * but fail the auth in rpc__gssauth_cn_fmt_srvr_resp() 2481 */ 2482 } else if (maj_stat != GSS_S_COMPLETE) { 2483 char msg[BUFSIZ]; 2484 rpc__gssauth_error_map(maj_stat, min_stat, 2485 gssauth_cn_info->gss_mech, 2486 msg, sizeof(msg), st); 2487 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL, 2488 ("(rpc__gssauth_cn_vfy_client_req): %s\n", msg)); 2489 return; 2490 } else { 2491 *st = rpc_s_ok; 2492 } 2493 2494 assoc_sec->krb_message.length = (unsigned32) output_token.length; 2495 assoc_sec->krb_message.data = output_token.value; 2496} 2497 2498/*****************************************************************************/ 2499/* 2500**++ 2501** 2502** ROUTINE NAME: rpc__gssauth_cn_vfy_srvr_resp 2503** 2504** SCOPE: INTERNAL - declared locally 2505** 2506** DESCRIPTION: 2507** 2508** This routine will decode auth_value field either an 2509** rpc_bind_ack or rpc_alter_context_response PDU. If the 2510** credentials field of the auth_value field contains an 2511** authentication protocol specific encoding of an error 2512** this will be returned as an error status code. This is 2513** called from the client side association state machine. 2514** Note that upon successful return the auth information 2515** rep will contain the client's authorization protocol 2516** and data. 2517** 2518** INPUTS: 2519** 2520** assoc_sec A pointer to per-association security context 2521** including association UUID CRC and sequence numbers. 2522** sec A pointer to security context element which includes 2523** the key ID, auth information rep and RPC auth 2524** information rep. 2525** auth_value A pointer to the auth_value field in the rpc_bind or 2526** rpc_alter_context PDU authentication trailer. 2527** auth_value_len The length, in bytes, of auth_value. 2528** 2529** INPUTS/OUTPUTS: none 2530** 2531** OUTPUTS: 2532** 2533** st The return status of this routine. 2534** 2535** IMPLICIT INPUTS: none 2536** 2537** IMPLICIT OUTPUTS: none 2538** 2539** FUNCTION VALUE: none 2540** 2541** SIDE EFFECTS: none 2542** 2543**-- 2544**/ 2545 2546INTERNAL void rpc__gssauth_cn_vfy_srvr_resp 2547( 2548 rpc_cn_assoc_sec_context_p_t assoc_sec, 2549 rpc_cn_sec_context_p_t sec, 2550 dce_pointer_t auth_value, 2551 unsigned32 auth_value_len, 2552 unsigned32 *st 2553) 2554{ 2555 rpc_gssauth_info_p_t gssauth_info = (rpc_gssauth_info_p_t)sec->sec_info; 2556 rpc_gssauth_cn_info_p_t gssauth_cn_info = (rpc_gssauth_cn_info_p_t)sec->sec_cn_info; 2557 OM_uint32 maj_stat; 2558 OM_uint32 min_stat; 2559 gss_buffer_desc input_token, output_token = GSS_C_EMPTY_BUFFER; 2560 2561 CODING_ERROR(st); 2562 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 2563 ("(rpc__gssauth_cn_vfy_srvr_resp)\n")); 2564 2565 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_PKT, 2566 ("(rpc__gssauth_cn_vfy_server_resp) prot->%x level->%x key_id->%x assoc_uuid_crc->%x xmit_seq->%x recv_seq->%x\n", 2567 sec->sec_info->authn_protocol, 2568 sec->sec_info->authn_level, 2569 sec->sec_key_id, 2570 assoc_sec->assoc_uuid_crc, 2571 assoc_sec->assoc_next_snd_seq, 2572 assoc_sec->assoc_next_rcv_seq)); 2573 2574#ifdef DEBUG 2575 if (RPC_DBG_EXACT(rpc_es_dbg_cn_errors, RPC_C_CN_DBG_AUTH_VFY_SERVER_RESP)) { 2576 *st = RPC_S_CN_DBG_AUTH_FAILURE; 2577 return; 2578 } 2579#endif 2580 2581 if (gssauth_cn_info->gss_ctx != GSS_C_NO_CONTEXT && 2582 gssauth_cn_info->gss_stat == GSS_S_COMPLETE) { 2583 /* todo only when ready */ 2584 goto done; 2585 } 2586 2587 input_token.value = auth_value; 2588 input_token.length = auth_value_len; 2589 maj_stat = rpc__gssauth_verify_server_token(&min_stat, 2590 sec, 2591 gssauth_info->gss_creds, 2592 gssauth_info->gss_server_name, 2593 gssauth_cn_info->gss_ctx, 2594 input_token, 2595 &gssauth_cn_info->gss_mech, 2596 &output_token); 2597 gssauth_cn_info->gss_stat = maj_stat; 2598 if (maj_stat == GSS_S_CONTINUE_NEEDED) { 2599 char msg[BUFSIZ]; 2600 rpc__gssauth_error_map(maj_stat, min_stat, 2601 gssauth_cn_info->gss_mech, 2602 msg, sizeof(msg), st); 2603 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL, 2604 ("(rpc__gssauth_cn_vfy_srvr_resp): %s: output_token.length[%u]\n", 2605 msg, (unsigned int)output_token.length)); 2606 /* 2607 * we still transfer the buffer to the client 2608 * but fail the auth in rpc__gssauth_cn_fmt_srvr_resp() 2609 */ 2610 } else if (maj_stat != GSS_S_COMPLETE) { 2611 char msg[BUFSIZ]; 2612 rpc__gssauth_error_map(maj_stat, min_stat, 2613 gssauth_cn_info->gss_mech, 2614 msg, sizeof(msg), st); 2615 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL, 2616 ("(rpc__gssauth_cn_vfy_srvr_resp): %s\n", msg)); 2617 return; 2618 } 2619 2620done: 2621 assoc_sec->krb_message.length = (unsigned32) output_token.length; 2622 assoc_sec->krb_message.data = output_token.value; 2623 2624 *st = rpc_s_ok; 2625} 2626 2627PRIVATE rpc_protocol_id_t rpc__gssauth_negotiate_cn_init 2628( 2629 rpc_auth_rpc_prot_epv_p_t *epv, 2630 unsigned32 *st 2631) 2632{ 2633 CODING_ERROR(st); 2634 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 2635 ("(rpc__gssauth_negotiate_cn_init)\n")); 2636 2637 *epv = (rpc_auth_rpc_prot_epv_p_t)&rpc_g_gssauth_negotiate_cn_epv; 2638 *st = rpc_s_ok; 2639 return RPC_C_PROTOCOL_ID_NCACN; 2640} 2641 2642PRIVATE rpc_protocol_id_t rpc__gssauth_mskrb_cn_init 2643( 2644 rpc_auth_rpc_prot_epv_p_t *epv, 2645 unsigned32 *st 2646) 2647{ 2648 CODING_ERROR(st); 2649 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 2650 ("(rpc__gssauth_mskrb_cn_init)\n")); 2651 2652 *epv = (rpc_auth_rpc_prot_epv_p_t)&rpc_g_gssauth_mskrb_cn_epv; 2653 *st = rpc_s_ok; 2654 return RPC_C_PROTOCOL_ID_NCACN; 2655} 2656 2657PRIVATE rpc_protocol_id_t rpc__gssauth_winnt_cn_init 2658( 2659 rpc_auth_rpc_prot_epv_p_t *epv, 2660 unsigned32 *st 2661) 2662{ 2663 CODING_ERROR(st); 2664 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 2665 ("(rpc__gssauth_winnt_cn_init)\n")); 2666 2667 *epv = (rpc_auth_rpc_prot_epv_p_t)&rpc_g_gssauth_winnt_cn_epv; 2668 *st = rpc_s_ok; 2669 return RPC_C_PROTOCOL_ID_NCACN; 2670} 2671 2672PRIVATE rpc_protocol_id_t rpc__gssauth_netlogon_cn_init 2673( 2674 rpc_auth_rpc_prot_epv_p_t *epv, 2675 unsigned32 *st 2676) 2677{ 2678 CODING_ERROR(st); 2679 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 2680 ("(rpc__gssauth_netlogon_cn_init)\n")); 2681 2682 *epv = (rpc_auth_rpc_prot_epv_p_t)&rpc_g_gssauth_netlogon_cn_epv; 2683 *st = rpc_s_ok; 2684 return RPC_C_PROTOCOL_ID_NCACN; 2685} 2686 2687#endif /* defined(AUTH_GSS_NEGOTIATE) && AUTH_GSS_NEGOTIATE */ 2688