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** 79** NAME 80** 81** schnauth.c 82** 83** FACILITY: 84** 85** Remote Procedure Call (RPC) 86** 87** ABSTRACT: 88** 89** Client-side support of netlogon/schannel module. 90** 91** 92*/ 93 94#include <dce/schannel.h> 95#include <schnauth.h> 96 97/* 98 * Size of buffer used when asking for remote server's principal name 99 */ 100#define MAX_SERVER_PRINC_NAME_LEN 500 101 102GLOBAL unsigned32 rpc_g_schnauth_alloc_count = 0; 103GLOBAL unsigned32 rpc_g_schnauth_free_count = 0; 104 105INTERNAL rpc_auth_rpc_prot_epv_p_t rpc_g_schnauth_rpc_prot_epv[RPC_C_PROTOCOL_ID_MAX]; 106 107INTERNAL void rpc__schnauth_inq_access_token( 108 rpc_auth_info_p_t auth_info, 109 rpc_access_token_p_t* token, 110 unsigned32 *stp 111 ); 112 113INTERNAL rpc_auth_epv_t rpc_g_schnauth_epv = 114{ 115 rpc__schnauth_bnd_set_auth, 116 rpc__schnauth_srv_reg_auth, 117 rpc__schnauth_mgt_inq_def, 118 rpc__schnauth_inq_my_princ_name, 119 rpc__schnauth_free_info, 120 rpc__schnauth_free_key, 121 rpc__schnauth_resolve_identity, 122 rpc__schnauth_release_identity, 123 rpc__schnauth_inq_sec_context, 124 rpc__schnauth_inq_access_token, 125}; 126 127/* 128 * R P C _ _ S C H N A U T H _ B N D _ S E T _ A U T H 129 * 130 */ 131 132PRIVATE void rpc__schnauth_bnd_set_auth 133( 134 unsigned_char_p_t server_name, 135 rpc_authn_level_t level, 136 rpc_auth_identity_handle_t auth_ident, 137 rpc_authz_protocol_id_t authz_prot, 138 rpc_binding_handle_t binding_h ATTRIBUTE_UNUSED, 139 rpc_auth_info_p_t *infop, 140 unsigned32 *stp 141) 142{ 143 int st = rpc_s_ok; 144 rpc_schnauth_info_p_t schnauth_info = NULL; 145 rpc_schannel_auth_info_p_t auth_info = NULL; 146 147 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 148 ("(rpc__schnauth_bnd_set_auth)\n")); 149 150 auth_info = (rpc_schannel_auth_info_p_t)auth_ident; 151 152 rpc_g_schnauth_alloc_count++; 153 RPC_MEM_ALLOC(schnauth_info, rpc_schnauth_info_p_t, sizeof(*schnauth_info), 154 RPC_C_MEM_UTIL, RPC_C_MEM_WAITOK); 155 156 /* I don't know yet why it has to be either of values */ 157 if ((authz_prot != rpc_c_authz_name) && 158 (authz_prot != rpc_c_authz_dce)) 159 { 160 st = rpc_s_authn_authz_mismatch; 161 goto poison; 162 } 163 164 /* Enable default level of protection as well as sign&seal of rpc traffic */ 165 if ((level != rpc_c_authn_level_default) && 166 (level != rpc_c_authn_level_pkt_integrity) && 167 (level != rpc_c_authn_level_pkt_privacy)) 168 { 169 st = rpc_s_unsupported_authn_level; 170 goto poison; 171 } 172 173 if (auth_info->domain_name != NULL) { 174 server_name = rpc_stralloc(auth_info->domain_name); 175 if (server_name == NULL) { 176 st = rpc_s_no_memory; 177 goto poison; 178 } 179 } 180 181 RPC_DBG_PRINTF(rpc_e_dbg_auth, 1, ( 182 "(rpc__schnauth_bnd_set_auth) %x created (now %d active)\n", 183 schnauth_info, rpc_g_schnauth_alloc_count - rpc_g_schnauth_free_count)); 184 185 memset(schnauth_info, 0, sizeof(*schnauth_info)); 186 187 RPC_MUTEX_INIT(schnauth_info->lock); 188 189 schnauth_info->auth_info.server_princ_name = server_name; 190 schnauth_info->auth_info.authn_level = level; 191 schnauth_info->auth_info.authn_protocol = rpc_c_authn_schannel; 192 schnauth_info->auth_info.authz_protocol = authz_prot; 193 schnauth_info->auth_info.is_server = 0; 194 schnauth_info->auth_info.u.auth_identity = auth_ident; 195 196 schnauth_info->auth_info.refcount = 1; 197 198 /* copy schannel data */ 199 memcpy(schnauth_info->sec_ctx.session_key, auth_info->session_key, 16); 200 201 schnauth_info->sec_ctx.domain_name = rpc_stralloc(auth_info->domain_name); 202 if (schnauth_info->sec_ctx.domain_name == NULL) { 203 st = rpc_s_no_memory; 204 goto poison; 205 } 206 207 schnauth_info->sec_ctx.fqdn = rpc_stralloc(auth_info->fqdn); 208 if (schnauth_info->sec_ctx.fqdn == NULL) { 209 st = rpc_s_no_memory; 210 goto poison; 211 } 212 213 schnauth_info->sec_ctx.machine_name = rpc_stralloc(auth_info->machine_name); 214 if (schnauth_info->sec_ctx.machine_name == NULL) { 215 st = rpc_s_no_memory; 216 goto poison; 217 } 218 219 /* setting auth info on binding handle means that we're initiating 220 schannel connection, so ensure "rpc_schn_initiator_flags" set */ 221 schnauth_info->sec_ctx.sender_flags = rpc_schn_initiator_flags | 222 auth_info->sender_flags; 223 224poison: 225 *infop = (rpc_auth_info_p_t) &schnauth_info->auth_info; 226 *stp = st; 227} 228 229PRIVATE void rpc__schnauth_init 230( 231 rpc_auth_epv_p_t *epv, 232 rpc_auth_rpc_prot_epv_tbl_t *rpc_prot_epv, 233 unsigned32 *st 234); 235 236#include <comp.h> 237void rpc__schnauth_init_func(void) 238{ 239 static rpc_authn_protocol_id_elt_t auth[1] = { 240 { rpc__schnauth_init, 241 rpc_c_authn_schannel, 242 dce_c_rpc_authn_protocol_schannel, 243 NULL, 244 rpc_g_schnauth_rpc_prot_epv } 245 }; 246 247 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 248 ("(rpc__module_init_func)\n")); 249 250 rpc__register_authn_protocol(auth, 1); 251} 252 253/* 254 * R P C _ _ S C H N A U T H _ I N I T 255 * 256 * Initialize the world. 257 */ 258 259PRIVATE void rpc__schnauth_init 260( 261 rpc_auth_epv_p_t *epv, 262 rpc_auth_rpc_prot_epv_tbl_t *rpc_prot_epv, 263 unsigned32 *st 264) 265{ 266 unsigned32 prot_id; 267 rpc_auth_rpc_prot_epv_t *prot_epv; 268 unsigned32 dbg_st; 269 270 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 271 ("(rpc__schnauth_init)\n")); 272 273 prot_id = rpc__schnauth_cn_init(&prot_epv, st); 274 if (*st == rpc_s_ok) 275 { 276 rpc_g_schnauth_rpc_prot_epv[prot_id] = prot_epv; 277 } 278 279 /* 280 * Return information for this (Netlogon/Schannel) authentication service. 281 */ 282 *epv = &rpc_g_schnauth_epv; 283 *rpc_prot_epv = rpc_g_schnauth_rpc_prot_epv; 284 285 *st = rpc_s_ok; 286} 287 288/* 289 * R P C _ _ S C H N A U T H _ F R E E _ I N F O 290 * 291 * Free info. 292 */ 293 294PRIVATE void rpc__schnauth_free_info 295( 296 rpc_auth_info_p_t *info 297) 298{ 299 rpc_schnauth_info_p_t schnauth_info = (rpc_schnauth_info_p_t)*info ; 300 char *info_type; 301 unsigned32 tst; 302 303 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 304 ("(rpc__schnauth_free_info)\n")); 305 306 info_type = (*info)->is_server?"server":"client"; 307 308 RPC_MUTEX_DELETE(schnauth_info->lock); 309 310 if ((*info)->server_princ_name) 311 { 312 rpc_string_free(&(*info)->server_princ_name, &tst); 313 } 314 315 (*info)->u.s.privs = 0; 316 317 if (schnauth_info->sec_ctx.machine_name) 318 { 319 rpc_string_free(&schnauth_info->sec_ctx.machine_name, &tst); 320 } 321 322 if (schnauth_info->sec_ctx.domain_name) 323 { 324 rpc_string_free(&schnauth_info->sec_ctx.domain_name, &tst); 325 } 326 327 if (schnauth_info->sec_ctx.fqdn) 328 { 329 rpc_string_free(&schnauth_info->sec_ctx.fqdn, &tst); 330 } 331 332 memset(schnauth_info, 0x69, sizeof(*schnauth_info)); 333 RPC_MEM_FREE(schnauth_info, RPC_C_MEM_UTIL); 334 rpc_g_schnauth_free_count++; 335 RPC_DBG_PRINTF(rpc_e_dbg_auth, 1, ( 336 "(rpc__schnauth_release) freeing %s auth_info (now %d active).\n", 337 info_type, rpc_g_schnauth_alloc_count - rpc_g_schnauth_free_count)); 338 *info = NULL; 339} 340 341/* 342 * R P C _ _ S C H N A U T H _ M G T _ I N Q _ D E F 343 * 344 * Return default authentication level 345 * 346 * !!! should read this from a config file. 347 */ 348 349PRIVATE void rpc__schnauth_mgt_inq_def 350( 351 unsigned32 *authn_level, 352 unsigned32 *stp 353) 354{ 355 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 356 ("(rpc__schnauth_mgt_inq_def)\n")); 357 358 *authn_level = rpc_c_authn_level_pkt_privacy; 359 *stp = rpc_s_ok; 360} 361 362/* 363 * R P C _ _ S C H N A U T H _ S R V _ R E G _ A U T H 364 * 365 */ 366 367PRIVATE void rpc__schnauth_srv_reg_auth 368( 369 unsigned_char_p_t server_name ATTRIBUTE_UNUSED, 370 rpc_auth_key_retrieval_fn_t get_key_func ATTRIBUTE_UNUSED, 371 dce_pointer_t arg ATTRIBUTE_UNUSED, 372 unsigned32 *stp 373) 374{ 375 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 376 ("(rpc__schnauth_srv_reg_auth)\n")); 377 378 *stp = rpc_s_ok; 379} 380 381/* 382 * R P C _ _ S C H N A U T H _ I N Q _ M Y _ P R I N C _ N A M E 383 * 384 * All this doesn't matter for this module, but we need the placebo. 385 */ 386 387PRIVATE void rpc__schnauth_inq_my_princ_name 388( 389 unsigned32 name_size, 390 unsigned_char_p_t name, 391 unsigned32 *stp 392) 393{ 394 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 395 ("(rpc__schnauth_inq_my_princ_name)\n")); 396 397 if (name_size > 0) { 398 rpc__strncpy(name, (unsigned char *)"", name_size - 1); 399 } 400 *stp = rpc_s_ok; 401} 402 403/* 404 * R P C _ _ S C H N A U T H _ F R E E _ K E Y 405 * 406 */ 407 408PRIVATE void rpc__schnauth_free_key 409( 410 rpc_key_info_p_t *key_info ATTRIBUTE_UNUSED 411) 412{ 413 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 414 ("(rpc__schnauth_free_key)\n")); 415} 416 417/* 418 * R P C _ _ S C H N A U T H _ R E S O L V E _ I D E N T I T Y 419 * 420 */ 421 422PRIVATE error_status_t rpc__schnauth_resolve_identity 423( 424 rpc_auth_identity_handle_t in_identity ATTRIBUTE_UNUSED, 425 rpc_auth_identity_handle_t *out_identity ATTRIBUTE_UNUSED 426) 427{ 428 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 429 ("(rpc__schnauth_resolve_identity)\n")); 430 431 *out_identity = in_identity; 432 return rpc_s_ok; 433} 434 435/* 436 * R P C _ _ S C H N A U T H _ R E L E A S E _ I D E N T I T Y 437 * 438 */ 439 440PRIVATE void rpc__schnauth_release_identity 441( 442 rpc_auth_identity_handle_t *identity ATTRIBUTE_UNUSED 443) 444{ 445 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 446 ("(rpc__schnauth_release_identity)\n")); 447} 448 449/* 450 * R P C _ _ S C H N A U T H _ I N Q _ S E C _ C O N T E X T 451 * 452 */ 453 454PRIVATE void rpc__schnauth_inq_sec_context 455( 456 rpc_auth_info_p_t auth_info ATTRIBUTE_UNUSED, 457 void **mech_context, 458 unsigned32 *st 459) 460{ 461 RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, 462 ("(rpc__schnauth_inq_sec_context)\n")); 463 464 /* This function is for the server side of schannel which 465 we don't support yet */ 466 *mech_context = NULL; 467 468 *st = rpc_s_ok; 469} 470 471INTERNAL void rpc__schnauth_inq_access_token( 472 rpc_auth_info_p_t auth_info, 473 rpc_access_token_p_t* token, 474 unsigned32 *stp 475 ) 476{ 477 *token = NULL; 478 *stp = rpc_s_ok; 479 480 return; 481} 482