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** rpcdep.c 82** 83** FACILITY: 84** 85** RPC Daemon 86** 87** ABSTRACT: 88** 89** The DCE 1.0 Endpoint Map (ep_) Manager. 90** 91** 92*/ 93 94#include <commonp.h> 95#include <com.h> 96#include <dce/ep.h> 97 98#include <rpcdp.h> 99#include <rpcdepdb.h> 100 101#ifdef RPC_LLB 102#include <dce/glb.h> 103#include <rpcdlbdb.h> 104#endif 105 106#include <twrp.h> 107 108/* ====================================================================== */ 109/* 110 * DCE 1.0 ept_ manager routines. 111 */ 112 113GLOBAL ept_v3_0_epv_t ept_v3_0_mgr_epv = 114{ 115 ept_insert, 116 ept_delete, 117 ept_lookup, 118 ept_map, 119 ept_lookup_handle_free, 120 ept_inq_object, 121 ept_mgmt_delete 122}; 123 124/* 125 * If REMOTE_ENDPOINT_ACCESS is defined, this will preserve the 126 * pre 1.0.3 semantics (and gaping security hole) which allows 127 * an unauthenticated user to modify (or delete) the endpoint 128 * map on a remote host. 129 */ 130 131#ifndef REMOTE_ENDPOINT_ACCESS 132 133INTERNAL int is_unpriv_handle( handle_t h, error_status_t *st ) 134{ 135 136 error_status_t status,status1; 137 rpc_binding_vector_p_t bv; 138 handle_t binding; 139 unsigned_char_p_t stb,our_netaddr,client_netaddr; 140 unsigned32 i; 141 static unsigned_char_p_t *local_netaddr = NULL; 142 static unsigned32 addr_count = 0; 143 unsigned32 prot_seq = 0; 144 rpc_transport_info_handle_t info; 145 unsigned32 uid = (unsigned32) -1; 146 unsigned32 gid = (unsigned32) -1; 147 148 rpc_binding_inq_prot_seq(h, &prot_seq, &status); 149 150 if (! STATUS_OK(&status)) 151 { 152 *st = status; 153 return(1); 154 } 155 156 if (prot_seq == rpc_c_protseq_id_ncalrpc) 157 { 158 rpc_binding_inq_transport_info(h, &info, &status); 159 160 if (! STATUS_OK(&status)) 161 { 162 *st = status; 163 return(1); 164 } 165 166 rpc_lrpc_transport_info_inq_peer_eid(info, &uid, &gid); 167 168 *st = rpc_s_ok; 169 170 return (uid != 0); 171 } 172 173/* Get client network address from binding handle (client_netaddr) */ 174 175 rpc_binding_server_from_client(h,&binding,&status); 176 if (! STATUS_OK(&status)) 177 { 178 *st = status; 179 return(1); 180 } 181 rpc_binding_to_string_binding(binding,&stb,&status); 182 183 if (! STATUS_OK(&status)) 184 { 185 rpc_binding_free(&binding,&status1); 186 *st = status; 187 return(1); 188 } 189 rpc_binding_free(&binding,&status1); 190 191 rpc_string_binding_parse(stb,NULL,NULL,&client_netaddr,NULL,NULL,&status); 192 if (! STATUS_OK(&status)) 193 { 194 rpc_string_free(&stb,&status1); 195 *st = status; 196 return(1); 197 } 198 rpc_string_free(&stb,&status1); 199 200 /* 201 * Lookup all of the addresses which this node answers to. 202 * Cache these in static storage so we only do this work once. 203 */ 204 if (addr_count == 0) 205 { 206 rpc_server_inq_bindings(&bv,&status); 207 if (! STATUS_OK(&status)) 208 { 209 rpc_string_free(&client_netaddr,&status1); 210 *st = status; 211 return(1); 212 } 213 214 addr_count = bv->count; 215 local_netaddr = (unsigned_char_p_t *) malloc( 216 (size_t) (addr_count * sizeof(unsigned_char_p_t))); 217 if (local_netaddr == NULL) 218 { 219 rpc_string_free(&client_netaddr,&status1); 220 rpc_binding_vector_free(&bv,&status1); 221 *st = ept_s_no_memory; 222 return(1); 223 } 224 225 for ( i=0; i < bv->count; i++ ) 226 { 227 rpc_binding_to_string_binding(bv->binding_h[i],&stb,&status); 228 if (! STATUS_OK(&status)) 229 { 230 rpc_binding_vector_free(&bv,&status1); 231 rpc_string_free(&client_netaddr,&status1); 232 *st = status; 233 return(1); 234 } 235 rpc_string_binding_parse(stb,NULL,NULL, 236 &our_netaddr,NULL,NULL,&status); 237 if (! STATUS_OK(&status)) 238 { 239 rpc_binding_vector_free(&bv,&status1); 240 rpc_string_free(&stb,&status1); 241 rpc_string_free(&client_netaddr,&status1); 242 *st = status; 243 return(1); 244 } 245 246 local_netaddr[i] = our_netaddr; 247 rpc_string_free(&stb,&status1); 248 } 249 rpc_binding_vector_free(&bv,&status1); 250 } 251 252 /* 253 * Compare the addresses with the client address 254 */ 255 *st = rpc_s_ok; 256 for ( i=0; i < addr_count; i++ ) 257 { 258 if(strcmp((char*) client_netaddr, (char*) local_netaddr[i]) == 0) 259 { 260 rpc_string_free(&client_netaddr,&status1); 261 return(0); 262 } 263 } 264 rpc_string_free(&client_netaddr,&status1); 265 return(1); 266 267} 268 269#endif /* notdef REMOTE_ENDPOINT_ACCESS */ 270 271/* 272 * Check whether endpoint is a named pipe 273 */ 274PRIVATE boolean ept__is_ncacn_np( 275 ept_entry_p_t entry) 276{ 277 unsigned16 floor_count, count; 278 byte_p_t tower = entry->tower->tower_octet_string; 279 280 if (entry->tower->tower_length < TWR_C_TOWER_FLR_COUNT_SIZE) 281 { 282 return false; /* hopefully someone else will pick this up */ 283 } 284 285 memcpy((char *)&floor_count, tower, TWR_C_TOWER_FLR_COUNT_SIZE); 286 RPC_RESOLVE_ENDIAN_INT16 (floor_count); 287 288 tower += TWR_C_TOWER_FLR_COUNT_SIZE; 289 290 for ( count = 0; count < floor_count; count++ ) 291 { 292 unsigned16 id_size, addr_size; 293 unsigned8 id; 294 295 if (TWR_C_TOWER_FLR_LHS_COUNT_SIZE > 296 entry->tower->tower_length - (tower - entry->tower->tower_octet_string)) 297 { 298 return false; 299 } 300 memcpy ((char *)&id_size, tower, TWR_C_TOWER_FLR_LHS_COUNT_SIZE); 301 RPC_RESOLVE_ENDIAN_INT16 (id_size); 302 303 if (id_size == TWR_C_TOWER_PROT_ID_SIZE) 304 { 305 if ((unsigned) (TWR_C_TOWER_FLR_LHS_COUNT_SIZE + TWR_C_TOWER_PROT_ID_SIZE) > 306 entry->tower->tower_length - (tower - entry->tower->tower_octet_string)) 307 { 308 return false; 309 } 310 memcpy ((char *)&id, (char *)(tower + TWR_C_TOWER_FLR_LHS_COUNT_SIZE), 311 TWR_C_TOWER_PROT_ID_SIZE); 312 313 if (id == TWR_C_FLR_PROT_ID_NP) 314 { 315 return true; 316 } 317 } 318 319 /* skip this floor */ 320 if ((unsigned) (TWR_C_TOWER_FLR_LHS_COUNT_SIZE + id_size + TWR_C_TOWER_FLR_RHS_COUNT_SIZE) > 321 entry->tower->tower_length - (tower - entry->tower->tower_octet_string)) 322 { 323 return false; 324 } 325 memcpy ((char *)&addr_size, (char *)(tower + TWR_C_TOWER_FLR_LHS_COUNT_SIZE + 326 id_size), TWR_C_TOWER_FLR_RHS_COUNT_SIZE); 327 RPC_RESOLVE_ENDIAN_INT16 (addr_size); 328 329 if ((unsigned) ((TWR_C_TOWER_FLR_LHS_COUNT_SIZE + id_size + 330 TWR_C_TOWER_FLR_RHS_COUNT_SIZE + addr_size)) > 331 (entry->tower->tower_length - (tower - entry->tower->tower_octet_string))) 332 { 333 return false; 334 } 335 tower += TWR_C_TOWER_FLR_LHS_COUNT_SIZE + id_size + 336 TWR_C_TOWER_FLR_RHS_COUNT_SIZE + addr_size; 337 } 338 339 return false; 340} 341 342PRIVATE void ept_insert( 343 handle_t h, 344 unsigned32 num_ents, 345 ept_entry_t entries[], 346 boolean32 replace, 347 error_status_t *status) 348{ 349 epdb_handle_t epdb; 350 ept_entry_t *entp; 351 unsigned32 i; 352 error_status_t tmp_st; 353 354 epdb_handle_from_ohandle(h, &epdb, status); 355 if (! STATUS_OK(status)) 356 return; 357 358#ifndef REMOTE_ENDPOINT_ACCESS 359 if ( is_unpriv_handle(h,&tmp_st) ) 360 { 361 assert(status != NULL); 362 *status = ept_s_cant_perform_op; 363 return; 364 } 365#endif /* notdef REMOTE_ENDPOINT_ACCESS */ 366 367 for (i = 0, entp = &entries[0]; i < num_ents; i++, entp++) 368 { 369 /* 370 * Don't insert named pipe endpoints for the moment - there is 371 * no client side code to support them. 372 */ 373 if (ept__is_ncacn_np(entp)) 374 { 375 /* skip */ 376 continue; 377 } 378 379 epdb_insert(epdb, entp, replace, status); 380 if (! STATUS_OK(status)) 381 { 382 if (dflag) 383 show_st("ept_insert Unable to update endpoint database", status); 384 385 ept_delete(h, i, entries, &tmp_st); 386 return; 387 } 388 } 389} 390 391PRIVATE void ept_delete( 392 handle_t h, 393 unsigned32 num_ents, 394 ept_entry_t entries[], 395 error_status_t *status) 396 397{ 398 epdb_handle_t epdb; 399 ept_entry_t *entp; 400 unsigned32 i; 401 error_status_t tmp_st; 402 403 epdb_handle_from_ohandle(h, &epdb, status); 404 if (! STATUS_OK(status)) 405 return; 406 407#ifndef REMOTE_ENDPOINT_ACCESS 408 if ( is_unpriv_handle(h,&tmp_st) ) 409 { 410 assert(status != NULL); 411 *status = ept_s_cant_perform_op; 412 return; 413 } 414#endif /* notdef REMOTE_ENDPOINT_ACCESS */ 415 416 for (i = 0, entp = &entries[0]; i < num_ents; i++, entp++) 417 { 418 epdb_delete(epdb, entp, status); 419 if (! STATUS_OK(status)) 420 { 421 if (dflag) 422 show_st("ept_delete Unable to update endpoint database", status); 423 return; 424 } 425 } 426} 427 428PRIVATE void ept_lookup( 429 handle_t h, 430 unsigned32 inquiry_type, 431 uuid_p_t object, 432 rpc_if_id_p_t interface, 433 unsigned32 vers_option, 434 ept_lookup_handle_t *entry_handle, 435 unsigned32 max_ents, 436 unsigned32 *num_ents, 437 ept_entry_t entries[], 438 error_status_t *status) 439{ 440 epdb_handle_t epdb; 441 442 *num_ents = 0; 443 444 epdb_handle_from_ohandle(h, &epdb, status); 445 if (! STATUS_OK(status)) 446 return; 447 448 epdb_lookup(epdb, inquiry_type, object, interface, vers_option, entry_handle, 449 max_ents, num_ents, entries, status); 450 451 if (dflag) 452 printf("ept_lookup entry_handle %p *entry_handle %p *num_ents %lu\n", 453 entry_handle, *entry_handle, (unsigned long) *num_ents); 454} 455 456PRIVATE void ept_map( 457 handle_t h, 458 uuid_p_t object, 459 twr_p_t map_tower, 460 ept_lookup_handle_t *entry_handle, 461 unsigned32 max_towers, 462 unsigned32 *num_towers, 463 twr_t *towers[], 464 error_status_t *status) 465{ 466 epdb_handle_t epdb; 467 468 *num_towers = 0; 469 470 epdb_handle_from_ohandle(h, &epdb, status); 471 if (! STATUS_OK(status)) 472 return; 473 474 epdb_map(epdb, object, map_tower, entry_handle, 475 max_towers, num_towers, towers, status); 476 477#ifdef RPC_LLB 478 if ((*status == ept_s_not_registered) || 479 (*status == ept_s_invalid_context) || 480 /* 481 * If finished with ept dbase, search llb dbase 482 */ 483 ((*status == rpc_s_ok) && 484 ((*num_towers < max_towers) || 485 ((entry_handle != NULL) && (*entry_handle == NULL)) )) ) 486 { 487 h = lbdb_inq_handle(); 488 lbdb_map(h, object, map_tower, entry_handle, 489 max_towers, num_towers, towers, status); 490 491 } 492#endif 493 494 if (dflag) 495 printf("ept_map entry_handle %p *entry_handle %p *num_towers %lu\n", 496 entry_handle, *entry_handle, (unsigned long) *num_towers); 497} 498 499PRIVATE void ept_lookup_handle_free( 500 handle_t h ATTRIBUTE_UNUSED, 501 ept_lookup_handle_t *entry_handle, 502 error_status_t *status) 503{ 504 epdb_handle_t epdb; 505 506 epdb = epdb_inq_handle(); 507 epdb_delete_lookup_handle(epdb, entry_handle); 508 509 SET_STATUS_OK(status); 510} 511 512PRIVATE void ept_inq_object( 513 handle_t h, 514 idl_uuid_t *object, 515 error_status_t *status) 516{ 517 epdb_handle_t epdb; 518 519 epdb_handle_from_ohandle(h, &epdb, status); 520 if (! STATUS_OK(status)) 521 return; 522 523 epdb_inq_object(epdb, object, status); 524} 525 526PRIVATE void ept_mgmt_delete( 527 handle_t h, 528 boolean32 object_speced, 529 uuid_p_t object, 530 twr_p_t tower, 531 error_status_t *status) 532{ 533 epdb_handle_t epdb; 534 error_status_t tmp_st; 535 536 epdb_handle_from_ohandle(h, &epdb, status); 537 if (! STATUS_OK(status)) 538 return; 539 540#ifndef REMOTE_ENDPOINT_ACCESS 541 if ( is_unpriv_handle(h,&tmp_st) ) 542 { 543 assert(status != NULL); 544 *status = ept_s_cant_perform_op; 545 return; 546 } 547#endif /* notdef REMOTE_ENDPOINT_ACCESS */ 548 549 epdb_mgmt_delete(epdb, object_speced, object, tower, status); 550} 551 552PRIVATE void ept_lookup_handle_t_rundown( 553 ept_lookup_handle_t entry_handle) 554{ 555 epdb_handle_t epdb; 556 557 epdb = epdb_inq_handle(); 558 epdb_delete_lookup_handle(epdb, &entry_handle); 559} 560