rpc_binding::~rpc_binding() { if (binding_handle) { error_status_t status; rpc_network_close(binding_handle, &status); rpc_binding_free(&binding_handle, &status); } }
DWORD VmDirRpcFreeBinding( handle_t* pBinding ) { DWORD dwError = ERROR_SUCCESS; #if !defined(_WIN32) || defined(HAVE_DCERPC_WIN32) rpc_binding_free(pBinding, &dwError); #else dwError = RpcBindingFree(pBinding); #endif return dwError; }
VMDNS_API VOID VmDnsCloseServer(PVMDNS_SERVER_CONTEXT pServerContext) { if(pServerContext) { if (pServerContext->hBinding) { DWORD dwError = 0; rpc_binding_free(&pServerContext->hBinding, &dwError); pServerContext->hBinding = NULL; } VMDNS_SAFE_FREE_MEMORY(pServerContext); } }
VOID FreeRpcBinding( PVOID *phBinding, RPC_BINDING_TYPE eBindingType ) { unsigned32 rpcStatus = RPC_S_OK; PVOID hBinding = NULL; if (phBinding) return; hBinding = *phBinding; switch (eBindingType) { case RPC_LSA_BINDING: LsaFreeBinding(hBinding); break; case RPC_SAMR_BINDING: SamrFreeBinding(hBinding); break; case RPC_NETLOGON_BINDING: NetrFreeBinding(hBinding); break; case RPC_DSSETUP_BINDING: DsrFreeBinding(hBinding); break; case RPC_WKSSVC_BINDING: WkssFreeBinding(hBinding); break; default: if (phBinding && *phBinding) { rpc_binding_free((handle_t*)phBinding, &rpcStatus); } break; } *phBinding = NULL; }
DWORD VMCAGetClientName(handle_t IDL_handle) { #if DEBUG_RPC rpc_binding_handle_t Srv; PSTR pszBinding = NULL; PSTR pszObjUUID = NULL; PSTR pszProtoSeq = NULL; PSTR pszNetworkAddress = NULL; PSTR pszEndPoint = NULL; PSTR pszNetworkOptions = NULL; unsigned32 rs = 0; rpc_binding_server_from_client (IDL_handle, &Srv, &rs); BAIL_ON_VMCA_ERROR(rs); rpc_binding_to_string_binding(Srv, (unsigned char **) &pszBinding, &rs); printf("Binding Info : %s\n", pszBinding); rpc_binding_free(&Srv, &rs); rpc_string_binding_parse(pszBinding, (unsigned_char_t **) &pszObjUUID, (unsigned_char_t **) &pszProtoSeq, (unsigned_char_t **) &pszNetworkAddress, (unsigned_char_t **) &pszEndPoint, (unsigned_char_t **) &pszNetworkOptions, &rs); printf("Obj UUID : %s, Proto : %s, Network : %s, \ EndPoint %s, Network Options : %s \n", pszObjUUID, pszProtoSeq, pszNetworkAddress, pszEndPoint, pszNetworkOptions); rpc_string_free((unsigned_char_t **) &pszBinding, &rs); rpc_string_free((unsigned_char_t **) &pszObjUUID, &rs); rpc_string_free((unsigned_char_t **) &pszProtoSeq, &rs); rpc_string_free((unsigned_char_t **) &pszNetworkAddress, &rs); rpc_string_free((unsigned_char_t **) &pszEndPoint, &rs); rpc_string_free((unsigned_char_t **) &pszNetworkOptions, &rs); #endif return 0; }
VOID LsaFreeBinding( IN OUT PLSA_BINDING phBinding ) { unsigned32 rpcStatus = RPC_S_OK; /* Free the binding itself */ if (phBinding && *phBinding) { rpc_binding_free((handle_t*)phBinding, &rpcStatus); BAIL_ON_RPC_STATUS(rpcStatus); *phBinding = NULL; } cleanup: return; error: goto cleanup; }
INTERNAL int is_unpriv_handle( handle_t h, error_status_t *st ) { error_status_t status,status1; rpc_binding_vector_p_t bv; handle_t binding; unsigned_char_p_t stb,our_netaddr,client_netaddr; unsigned32 i; static unsigned_char_p_t *local_netaddr = NULL; static unsigned32 addr_count = 0; unsigned32 prot_seq = 0; rpc_transport_info_handle_t info; unsigned32 uid = (unsigned32) -1; unsigned32 gid = (unsigned32) -1; rpc_binding_inq_prot_seq(h, &prot_seq, &status); if (! STATUS_OK(&status)) { *st = status; return(1); } if (prot_seq == rpc_c_protseq_id_ncalrpc) { rpc_binding_inq_transport_info(h, &info, &status); if (! STATUS_OK(&status)) { *st = status; return(1); } rpc_lrpc_transport_info_inq_peer_eid(info, &uid, &gid); *st = rpc_s_ok; return (uid != 0); } /* Get client network address from binding handle (client_netaddr) */ rpc_binding_server_from_client(h,&binding,&status); if (! STATUS_OK(&status)) { *st = status; return(1); } rpc_binding_to_string_binding(binding,&stb,&status); if (! STATUS_OK(&status)) { rpc_binding_free(&binding,&status1); *st = status; return(1); } rpc_binding_free(&binding,&status1); rpc_string_binding_parse(stb,NULL,NULL,&client_netaddr,NULL,NULL,&status); if (! STATUS_OK(&status)) { rpc_string_free(&stb,&status1); *st = status; return(1); } rpc_string_free(&stb,&status1); /* * Lookup all of the addresses which this node answers to. * Cache these in static storage so we only do this work once. */ if (addr_count == 0) { rpc_server_inq_bindings(&bv,&status); if (! STATUS_OK(&status)) { rpc_string_free(&client_netaddr,&status1); *st = status; return(1); } addr_count = bv->count; local_netaddr = (unsigned_char_p_t *) malloc( (size_t) (addr_count * sizeof(unsigned_char_p_t))); if (local_netaddr == NULL) { rpc_string_free(&client_netaddr,&status1); rpc_binding_vector_free(&bv,&status1); *st = ept_s_no_memory; return(1); } for ( i=0; i < bv->count; i++ ) { rpc_binding_to_string_binding(bv->binding_h[i],&stb,&status); if (! STATUS_OK(&status)) { rpc_binding_vector_free(&bv,&status1); rpc_string_free(&client_netaddr,&status1); *st = status; return(1); } rpc_string_binding_parse(stb,NULL,NULL, &our_netaddr,NULL,NULL,&status); if (! STATUS_OK(&status)) { rpc_binding_vector_free(&bv,&status1); rpc_string_free(&stb,&status1); rpc_string_free(&client_netaddr,&status1); *st = status; return(1); } local_netaddr[i] = our_netaddr; rpc_string_free(&stb,&status1); } rpc_binding_vector_free(&bv,&status1); } /* * Compare the addresses with the client address */ *st = rpc_s_ok; for ( i=0; i < addr_count; i++ ) { if(strcmp((char*) client_netaddr, (char*) local_netaddr[i]) == 0) { rpc_string_free(&client_netaddr,&status1); return(0); } } rpc_string_free(&client_netaddr,&status1); return(1); }
static int rpc_netshareenum(struct smb_ctx *ctx, int *entriesp, int *totalp, struct share_info **entries_listp) { char ctx_string[2+16+1]; /* enough for 64-bit pointer, in hex */ unsigned_char_p_t binding; unsigned32 binding_status; rpc_binding_handle_t binding_h; int error, i, entries; char *addrstr, *srvnamestr; unsigned short *usrvnamestr; unsigned32 level; SHARE_ENUM_STRUCT share_info; SHARE_INFO_1_CONTAINER share_info_1_container; SHARE_INFO_1 *shares, *share; unsigned32 total_entries; unsigned32 status, free_status; struct share_info *entry_list, *elp; static EXCEPTION rpc_x_connect_rejected; static int exceptions_initialized; sprintf(ctx_string, "%p", ctx); rpc_string_binding_compose(NULL, "ncacn_np", ctx_string, "srvsvc", NULL, &binding, &binding_status); if (binding_status != rpc_s_ok) { smb_error(dgettext(TEXT_DOMAIN, "rpc_string_binding_compose failed with %d"), 0, binding_status); return (EINVAL); } rpc_binding_from_string_binding(binding, &binding_h, &status); rpc_string_free(&binding, (unsigned32 *)&free_status); if (binding_status != rpc_s_ok) { smb_error(dgettext(TEXT_DOMAIN, "rpc_binding_from_string_binding failed with %d"), 0, binding_status); return (EINVAL); } level = 1; share_info.share_union.level = 1; share_info.share_union.tagged_union.share1 = &share_info_1_container; share_info_1_container.share_count = 0; share_info_1_container.shares = NULL; /* * Convert the server IP address to a string, and send that as * the "server name" - that's what Windows appears to do, and * that avoids problems with NetBIOS names containing * non-ASCII characters. */ addrstr = inet_ntoa(ctx->ct_srvinaddr.sin_addr); srvnamestr = malloc(strlen(addrstr) + 3); if (srvnamestr == NULL) { status = errno; smb_error(dgettext(TEXT_DOMAIN, "can't allocate string for server address"), status); rpc_binding_free(&binding_h, &free_status); return (status); } strcpy(srvnamestr, "\\\\"); strcat(srvnamestr, addrstr); usrvnamestr = convert_utf8_to_leunicode(srvnamestr); if (usrvnamestr == NULL) { smb_error(dgettext(TEXT_DOMAIN, "can't convert string for server address to Unicode"), 0); rpc_binding_free(&binding_h, &free_status); free(srvnamestr); return (EINVAL); } if (!exceptions_initialized) { EXCEPTION_INIT(rpc_x_connect_rejected); exc_set_status(&rpc_x_connect_rejected, rpc_s_connect_rejected); exceptions_initialized = 1; } /* printf("Calling NetrShareEnum.."); XXX */ TRY status = NetrShareEnum(binding_h, usrvnamestr, &level, &share_info, 4294967295U, &total_entries, NULL); if (status != 0) smb_error(dgettext(TEXT_DOMAIN, "error from NetrShareEnum call: status = 0x%08x"), 0, status); /*CSTYLED*/ CATCH (rpc_x_connect_rejected) /* * This is what we get if we can't open the pipe. * That's a normal occurrence when we're talking * to a system that (presumably) doesn't support * DCE RPC on the server side, such as Windows 95/98/Me, * so we don't log an error. */ /*CSTYLED*/ status = ENOTSUP; CATCH_ALL /* * XXX - should we handle some exceptions differently, * returning different errors, and try RAP only for * ENOTSUP? */ smb_error(dgettext(TEXT_DOMAIN, "error from NetrShareEnum call: exception = %u"), 0, THIS_CATCH->match.value); status = ENOTSUP; ENDTRY rpc_binding_free(&binding_h, &free_status); free(srvnamestr); free(usrvnamestr); if (status != 0) return (ENOTSUP); /* * XXX - if the IDL is correct, it's not clear whether the * unmarshalling code will properly handle the case where * a packet where "share_count" and the max count for the * array of shares don't match; a valid DCE RPC implementation * won't marshal something like that, but there's no guarantee * that the server we're talking to has a valid implementation * (which could be a *malicious* implementation!). */ entries = share_info.share_union.tagged_union.share1->share_count; shares = share_info.share_union.tagged_union.share1->shares; entry_list = calloc(entries, sizeof (struct share_info)); if (entry_list == NULL) { error = errno; goto cleanup_and_return; } for (share = shares, elp = entry_list, i = 0; i < entries; i++, share++) { elp->type = share->shi1_type; elp->netname = convert_unicode_to_utf8(share->shi1_share); if (elp->netname == NULL) goto fail; elp->remark = convert_unicode_to_utf8(share->shi1_remark); if (elp->remark == NULL) goto fail; elp++; } *entriesp = entries; *totalp = total_entries; *entries_listp = entry_list; error = 0; goto cleanup_and_return; fail: error = errno; for (elp = entry_list, i = 0; i < entries; i++, elp++) { /* * elp->netname is set before elp->remark, so if * elp->netname is null, elp->remark is also null. * If either of them is null, we haven't done anything * to any entries after this one. */ if (elp->netname == NULL) break; free(elp->netname); if (elp->remark == NULL) break; free(elp->remark); } free(entry_list); cleanup_and_return: for (share = shares, i = 0; i < entries; i++, share++) { free(share->shi1_share); free(share->shi1_remark); } free(shares); /* * XXX - "share1" should be a unique pointer, but we haven't * changed the marshalling code to support non-full pointers * in unions, so we leave it as a full pointer. * * That means that this might, or might not, be changed from * pointing to "share_info_1_container" to pointing to a * mallocated structure, according to the DCE RPC 1.1 IDL spec; * we free it only if it's changed. */ if (share_info.share_union.tagged_union.share1 != &share_info_1_container) free(share_info.share_union.tagged_union.share1); return (error); }
static NTSTATUS LsaInitBindingFullA( OUT PLSA_BINDING phBinding, IN PCSTR pszProtSeq, IN PCSTR pszHostname, IN PCSTR pszEndpoint, IN PCSTR pszUuid, IN PCSTR pszOptions, IN PIO_CREDS pCreds ) { NTSTATUS ntStatus = STATUS_SUCCESS; unsigned32 rpcStatus = RPC_S_OK; unsigned32 rpcStatus2 = RPC_S_OK; PBYTE pbBindingString = NULL; PBYTE pbProtSeq = NULL; PBYTE pbEndpoint = NULL; PBYTE pbUuid = NULL; PBYTE pbOpts = NULL; PBYTE pbAddr = NULL; handle_t hBinding = NULL; rpc_transport_info_handle_t hInfo = NULL; BAIL_ON_INVALID_PTR(phBinding, ntStatus); BAIL_ON_INVALID_PTR(pszProtSeq, ntStatus); pbProtSeq = (PBYTE)strdup(pszProtSeq); BAIL_ON_NULL_PTR(pbProtSeq, ntStatus); if (pszEndpoint != NULL) { pbEndpoint = (PBYTE) strdup(pszEndpoint); BAIL_ON_NULL_PTR(pbEndpoint, ntStatus); } if (pszUuid != NULL) { pbUuid = (PBYTE)strdup(pszUuid); BAIL_ON_NULL_PTR(pbUuid, ntStatus); } if (pszOptions != NULL) { pbOpts = (PBYTE)strdup(pszOptions); BAIL_ON_NULL_PTR(pbOpts, ntStatus); } if (pszHostname) { pbAddr = (PBYTE)strdup(pszHostname); BAIL_ON_NULL_PTR(pbAddr, ntStatus); } rpc_string_binding_compose( pbUuid, pbProtSeq, pbAddr, pbEndpoint, pbOpts, &pbBindingString, &rpcStatus); BAIL_ON_RPC_STATUS(rpcStatus); rpc_binding_from_string_binding( pbBindingString, &hBinding, &rpcStatus); BAIL_ON_RPC_STATUS(rpcStatus); if (strcmp(pszProtSeq, "ncacn_np") == 0) { rpc_smb_transport_info_from_lwio_creds( pCreds, &hInfo, &rpcStatus); BAIL_ON_RPC_STATUS(rpcStatus); rpc_binding_set_transport_info( hBinding, hInfo, &rpcStatus); BAIL_ON_RPC_STATUS(rpcStatus); hInfo = NULL; } rpc_mgmt_set_com_timeout(hBinding, 6, &rpcStatus); BAIL_ON_RPC_STATUS(rpcStatus); *phBinding = (LSA_BINDING)hBinding; cleanup: LW_SAFE_FREE_MEMORY(pbProtSeq); LW_SAFE_FREE_MEMORY(pbEndpoint); LW_SAFE_FREE_MEMORY(pbUuid); LW_SAFE_FREE_MEMORY(pbOpts); LW_SAFE_FREE_MEMORY(pbAddr); if (pbBindingString) { rpc_string_free(&pbBindingString, &rpcStatus2); } if ((rpcStatus == RPC_S_OK) && (rpcStatus2 != RPC_S_OK)) { rpcStatus = rpcStatus2; } if (hInfo) { rpc_smb_transport_info_free(hInfo); } if (ntStatus == STATUS_SUCCESS && rpcStatus != RPC_S_OK) { ntStatus = LwRpcStatusToNtStatus(rpcStatus); } return ntStatus; error: if (hBinding) { rpc_binding_free(&hBinding, &rpcStatus2); } if (phBinding) { *phBinding = NULL; } goto cleanup; }
PRIVATE void rpc__dg_binding_inq_client ( rpc_binding_rep_p_t binding_r, rpc_client_handle_t *client_h, unsigned32 *st ) { rpc_dg_binding_server_p_t shand = (rpc_dg_binding_server_p_t) binding_r; rpc_dg_scall_p_t scall = shand->scall; rpc_binding_handle_t h; dce_uuid_t cas_uuid; rpc_dg_client_rep_p_t client; unsigned32 temp_seq, tst; *st = rpc_s_ok; /* * Lock down and make sure we're in an OK state. */ RPC_LOCK(0); RPC_DG_CALL_LOCK(&scall->c); if (scall->c.state == rpc_e_dg_cs_orphan) { *st = rpc_s_call_orphaned; RPC_DG_CALL_UNLOCK(&scall->c); RPC_UNLOCK(0); return; } /* * See if there is already a client handle associated with the scte * associated with this server binding handle. If there is, just * return it. */ if (scall->scte->client != NULL) { *client_h = (rpc_client_handle_t) scall->scte->client; RPC_DG_CALL_UNLOCK(&scall->c); RPC_UNLOCK(0); return; } /* * No client handle. We need to do a call back to obtain a UUID * uniquely identifying this particular instance of the client. */ h = rpc__dg_sct_make_way_binding(scall->scte, st); RPC_DG_CALL_UNLOCK(&scall->c); RPC_UNLOCK(0); if (h == NULL) { return; } RPC_DBG_PRINTF(rpc_e_dbg_general, 3, ("(binding_inq_client) Doing whats-your-proc-id callback\n")); DCETHREAD_TRY { (*conv_v3_0_c_epv.conv_who_are_you2) (h, &scall->c.call_actid, rpc_g_dg_server_boot_time, &temp_seq, &cas_uuid, st); } DCETHREAD_CATCH_ALL(THIS_CATCH) { *st = rpc_s_who_are_you_failed; } DCETHREAD_ENDTRY rpc_binding_free(&h, &tst); if (*st != rpc_s_ok) return; /* * Check to see if the UUID returned has already been built into * a client handle associated with another scte. Since we have no * way of mapping actids to processes, we can't know that two actid * are in the same address space until we get the same address space * UUID from both. In this case it is necessary to use the same * client handle for both actids. */ RPC_LOCK(0); RPC_DG_CALL_LOCK(&scall->c); if (scall->c.state == rpc_e_dg_cs_orphan) { *st = rpc_s_call_orphaned; RPC_DG_CALL_UNLOCK(&scall->c); RPC_UNLOCK(0); return; } RPC_MUTEX_LOCK(monitor_mutex); client = find_client(&cas_uuid); if (client != NULL) { client->refcnt++; scall->scte->client = client; } else { /* * If not, alloc up a client handle structure and thread * it onto the table. */ unsigned16 probe; probe = CLIENT_HASH_PROBE(&cas_uuid, st); RPC_MEM_ALLOC(client, rpc_dg_client_rep_p_t, sizeof *client, RPC_C_MEM_DG_CLIENT_REP, RPC_C_MEM_NOWAIT); client->next = client_table[probe]; client->rundown = NULL; client->last_update = 0; client->cas_uuid = cas_uuid; client_table[probe] = client; scall->scte->client = client; client->refcnt = 2; } RPC_MUTEX_UNLOCK(monitor_mutex); RPC_DG_CALL_UNLOCK(&scall->c); RPC_UNLOCK(0); *client_h = (rpc_client_handle_t) client; }