DWORD VmDnsCheckAccess( handle_t IDL_handle, BOOL bNeedAdminPrivilage ) { DWORD dwError = 0; rpc_authz_cred_handle_t hPriv = { 0 }; DWORD dwProtectLevel = 0; ULONG rpc_status = rpc_s_ok; unsigned char *authPrinc = NULL; rpc_binding_inq_auth_caller( IDL_handle, &hPriv, &authPrinc, &dwProtectLevel, NULL, /* unsigned32 *authn_svc, */ NULL, /* unsigned32 *authz_svc, */ &rpc_status); /* Deny if connection is not encrypted */ if (dwProtectLevel < rpc_c_protect_level_pkt_privacy) { dwError = ERROR_ACCESS_DENIED; BAIL_ON_VMDNS_ERROR(dwError); } /* Deny if no auth identity is provided. */ if (rpc_status == rpc_s_binding_has_no_auth || !authPrinc || !*authPrinc) { dwError = ERROR_ACCESS_DENIED; BAIL_ON_VMDNS_ERROR(dwError); } if (bNeedAdminPrivilage) { dwError = VmDnsLdapAccessCheck(authPrinc, VMDNS_ADMINISTRATORS); BAIL_ON_VMDNS_ERROR(dwError); } error: if (authPrinc) { rpc_string_free((unsigned_char_t **)&authPrinc, &rpc_status); } return dwError; }
INTERNAL void rpc__ntlmauth_free_info ( rpc_auth_info_p_t *info ) { rpc_ntlmauth_info_p_t ntlmauth_info = NULL; unsigned32 st = 0; OM_uint32 minor_status = 0; RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_ROUTINE_TRACE, ("(rpc__ntlmauth_free_info)\n")); if (info == NULL || *info == NULL) { return; } ntlmauth_info = (rpc_ntlmauth_info_p_t)(*info); if (ntlmauth_info->auth_info.server_princ_name) { rpc_string_free(&ntlmauth_info->auth_info.server_princ_name, &st); } if (ntlmauth_info->gss_server_name) { gss_release_name(&minor_status, &ntlmauth_info->gss_server_name); } if (ntlmauth_info->gss_creds) { gss_release_cred(&minor_status, &ntlmauth_info->gss_creds); } memset(ntlmauth_info, 0, sizeof(*ntlmauth_info)); RPC_MEM_FREE(ntlmauth_info, RPC_C_MEM_NTLMAUTH_INFO); rpc_g_ntlmauth_free_count++; RPC_DBG_PRINTF(rpc_e_dbg_auth, RPC_C_CN_DBG_AUTH_GENERAL, ("(rpc__ntlmauth_free_info) freeing %s auth_info (now %d active).\n", ntlmauth_info->auth_info.is_server ? "server" : "client", rpc_g_ntlmauth_alloc_count - rpc_g_ntlmauth_free_count)); *info = NULL; }
/* * Create a new named server binding entry. */ static void rpc_ns__ldap_export_server_element(LDAP *ld, char *serverDN, rpc_if_handle_t if_spec, rpc_binding_vector_p_t vec, unsigned32 *status ) { unsigned_char_p_t dn = NULL, rdn = NULL; idl_uuid_t rdnUuid; /* Just create an arbitary UUID to name this entry. */ uuid_create(&rdnUuid, status); if (*status != rpc_s_ok) { goto out; } uuid_to_string(&rdnUuid, &rdn, status); if (*status != rpc_s_ok) { goto out; } RPC_MEM_ALLOC(dn, unsigned_char_p_t, strlen(serverDN) + strlen(rdn) + sizeof("CN=,"), RPC_C_MEM_NSRESOLUTION, RPC_C_MEM_WAITOK); sprintf(dn, "CN=%s,%s", rdn, serverDN); rpc_ns__ldap_export_server_element_ext(ld, dn, if_spec, vec, LDAP_MOD_ADD, status); out: if (dn != NULL) { RPC_MEM_FREE(dn, RPC_C_MEM_NSRESOLUTION); } if (rdn != NULL) { rpc_string_free(&rdn, status); } }
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; }
PRIVATE void rpc__ntlmauth_free_info ( rpc_auth_info_p_t *info ) { rpc_ntlmauth_info_p_t ntlmauth_info = (rpc_ntlmauth_info_p_t)*info ; char *info_type = (*info)->is_server?"server":"client"; unsigned32 tst; RPC_MUTEX_DELETE(ntlmauth_info->lock); if ((*info)->server_princ_name) rpc_string_free (&(*info)->server_princ_name, &tst); (*info)->u.s.privs = 0; // sec_id_pac_util_free (&ntlmauth_info->client_pac); memset (ntlmauth_info, 0x69, sizeof(*ntlmauth_info)); RPC_MEM_FREE (ntlmauth_info, RPC_C_MEM_UTIL); rpc_g_ntlmauth_free_count++; RPC_DBG_PRINTF(rpc_e_dbg_auth, 1, ( "(rpc__ntlmauth_release) freeing %s auth_info (now %d active).\n", info_type, rpc_g_ntlmauth_alloc_count - rpc_g_ntlmauth_free_count)); *info = NULL; }
BOOLEAN CreateRpcBinding( PVOID *phBinding, RPC_BINDING_TYPE eBindingType, PCWSTR pwszHostname, PCWSTR pwszBinding, PCREDENTIALS pCredentials ) { PCSTR pszNtlmsspAuth = "ntlmssp"; PCSTR pszSign = "sign"; PCSTR pszSeal = "seal"; BOOLEAN bRet = TRUE; NTSTATUS ntStatus = STATUS_SUCCESS; DWORD dwError = ERROR_SUCCESS; unsigned32 rpcStatus = RPC_S_OK; LSA_BINDING hBinding = NULL; LW_PIO_CREDS pIoCreds = NULL; PWSTR pwszBindingString = NULL; size_t sBindingStringLen = 0; PSTR pszBindingString = NULL; PSTR *ppszOptions = NULL; DWORD iOpt = 0; DWORD i = 0; DWORD dwNumValidOptions = 0; unsigned32 AuthType = 0; unsigned32 ProtectionLevel = 0; SEC_WINNT_AUTH_IDENTITY *pNtlmSspAuthInfo = NULL; PVOID pAuthInfo = NULL; unsigned char *pszUuid = NULL; unsigned char *pszProtSeq = NULL; unsigned char *pszNetworkAddr = NULL; unsigned char *pszEndpoint = NULL; unsigned char *pszOptions = NULL; PSTR pszHostname = NULL; if (phBinding == NULL) { ntStatus = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntStatus); } if (pwszBinding) { dwError = LwAllocateWc16String(&pwszBindingString, pwszBinding); BAIL_ON_WIN_ERROR(dwError); dwError = LwWc16sLen(pwszBindingString, &sBindingStringLen); BAIL_ON_WIN_ERROR(dwError); dwError = LwWc16sToMbs(pwszBindingString, &pszBindingString); BAIL_ON_WIN_ERROR(dwError); ppszOptions = get_string_list(pszBindingString, ':'); if (ppszOptions == NULL) { ntStatus = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntStatus); } /* * Find and identify valid options */ while (ppszOptions[iOpt]) { if (!strcasecmp(pszNtlmsspAuth, ppszOptions[iOpt])) { AuthType = rpc_c_authn_winnt; dwNumValidOptions++; } else if (!strcasecmp(pszSign, ppszOptions[iOpt])) { ProtectionLevel = rpc_c_authn_level_pkt_integrity; dwNumValidOptions++; } else if (!strcasecmp(pszSeal, ppszOptions[iOpt])) { ProtectionLevel = rpc_c_authn_level_pkt_privacy; dwNumValidOptions++; } iOpt++; } } /* * Cut off the options from the binding string so it can * be passed to rpc routines */ if (dwNumValidOptions > 0) { i = sBindingStringLen; while (dwNumValidOptions && pwszBindingString[--i]) { if (pwszBindingString[i] == (WCHAR)':') { dwNumValidOptions--; } } pwszBindingString[i] = (WCHAR)'\0'; pszBindingString[i] = '\0'; } ntStatus = LwIoGetActiveCreds(NULL, &pIoCreds); BAIL_ON_NT_STATUS(ntStatus); if (pwszBindingString) { ntStatus = RpcInitBindingFromBindingString( (handle_t*)&hBinding, pwszBindingString, pIoCreds); } else { switch (eBindingType) { case RPC_LSA_BINDING: ntStatus = LsaInitBindingDefault(&hBinding, pwszHostname, pIoCreds); break; case RPC_SAMR_BINDING: ntStatus = SamrInitBindingDefault(&hBinding, pwszHostname, pIoCreds); break; case RPC_NETLOGON_BINDING: ntStatus = NetrInitBindingDefault(&hBinding, pwszHostname, pIoCreds); break; case RPC_DSSETUP_BINDING: ntStatus = DsrInitBindingDefault(&hBinding, pwszHostname, pIoCreds); break; case RPC_WKSSVC_BINDING: ntStatus = WkssInitBindingDefault(&hBinding, pwszHostname, pIoCreds); break; default: ntStatus = STATUS_NOT_IMPLEMENTED; break; } } BAIL_ON_NT_STATUS(ntStatus); switch (AuthType) { case rpc_c_authn_winnt: dwError = LwAllocateMemory(sizeof(*pNtlmSspAuthInfo), OUT_PPVOID(&pNtlmSspAuthInfo)); BAIL_ON_WIN_ERROR(dwError); if (pCredentials->Ntlm.pwszDomain) { dwError = LwWc16sToMbs(pCredentials->Ntlm.pwszDomain, &pNtlmSspAuthInfo->Domain); BAIL_ON_WIN_ERROR(dwError); pNtlmSspAuthInfo->DomainLength = strlen(pNtlmSspAuthInfo->Domain); } dwError = LwWc16sToMbs(pCredentials->Ntlm.pwszUsername, &pNtlmSspAuthInfo->User); BAIL_ON_WIN_ERROR(dwError); pNtlmSspAuthInfo->UserLength = strlen(pNtlmSspAuthInfo->User); dwError = LwWc16sToMbs(pCredentials->Ntlm.pwszPassword, &pNtlmSspAuthInfo->Password); BAIL_ON_WIN_ERROR(dwError); pNtlmSspAuthInfo->PasswordLength = strlen(pNtlmSspAuthInfo->Password); pAuthInfo = (PVOID)pNtlmSspAuthInfo; break; default: pAuthInfo = NULL; break; } if (pwszHostname) { dwError = LwWc16sToMbs(pwszHostname, &pszHostname); BAIL_ON_WIN_ERROR(dwError); } else { rpc_string_binding_parse((unsigned char*)pszBindingString, &pszUuid, &pszProtSeq, &pszNetworkAddr, &pszEndpoint, &pszOptions, &rpcStatus); if (rpcStatus) { ntStatus = LwRpcStatusToNtStatus(rpcStatus); BAIL_ON_NT_STATUS(ntStatus); } dwError = LwAllocateString((PSTR)pszNetworkAddr, &pszHostname); BAIL_ON_WIN_ERROR(dwError); } if (AuthType) { rpc_binding_set_auth_info(hBinding, (unsigned char*)pszHostname, ProtectionLevel, AuthType, (rpc_auth_identity_handle_t)pAuthInfo, rpc_c_authz_name, /* authz_protocol */ &rpcStatus); if (rpcStatus) { ntStatus = LwRpcStatusToNtStatus(rpcStatus); BAIL_ON_NT_STATUS(ntStatus); } } *phBinding = hBinding; cleanup: if (pIoCreds) { LwIoDeleteCreds(pIoCreds); } LW_SAFE_FREE_MEMORY(pwszBindingString); LW_SAFE_FREE_MEMORY(pszBindingString); LW_SAFE_FREE_MEMORY(pszHostname); rpc_string_free(&pszUuid, &rpcStatus); rpc_string_free(&pszProtSeq, &rpcStatus); rpc_string_free(&pszNetworkAddr, &rpcStatus); rpc_string_free(&pszEndpoint, &rpcStatus); rpc_string_free(&pszOptions, &rpcStatus); if (ppszOptions) { free_string_list(ppszOptions); } if (ntStatus == STATUS_SUCCESS && dwError != ERROR_SUCCESS) { ntStatus = LwWin32ErrorToNtStatus(dwError); } if (ntStatus != STATUS_SUCCESS) { bRet = FALSE; } return bRet; error: *phBinding = NULL; bRet = FALSE; goto cleanup; }
static void rpc_ns__ldap_lookup_server_element(LDAP *ld, unsigned_char_p_t serverDN, rpc_if_handle_t if_spec, unsigned_char_p_t *dn, unsigned32 *status) { unsigned_char_p_t filter = NULL; unsigned_char_p_t uuid = NULL; rpc_if_id_t if_id; LDAPMessage *msg = NULL, *e; char *_dn; size_t len; rpc_if_inq_id(if_spec, &if_id, status); if (*status != rpc_s_ok) { goto out; } /* Get the interface ID */ uuid_to_string(&if_id.uuid, &uuid, status); if (*status != rpc_s_ok) { goto out; } len = strlen(uuid); len += sizeof("(&(objectClass=rpcServerElement)(rpcNsInterfaceID=,65535.65535))"); RPC_MEM_ALLOC(filter, unsigned_char_p_t, len, RPC_C_MEM_NSRESOLUTION, RPC_C_MEM_WAITOK); sprintf(filter, "(&(objectClass=rpcServerElement)(rpcNsInterfaceID=%s,%hu.%hu))", uuid, if_id.vers_major, if_id.vers_minor); if (ldap_search_s(ld, serverDN, LDAP_SCOPE_ONELEVEL, filter, NULL, 0, &msg) != LDAP_SUCCESS) { *status = rpc_s_not_found; goto out; } e = ldap_first_entry(ld, msg); if (e == NULL) { *status = rpc_s_not_found; goto out; } _dn = ldap_get_dn(ld, e); if (dn == NULL) { *status = rpc_s_not_found; goto out; } *dn = rpc_stralloc(_dn); ldap_memfree(_dn); out: if (filter != NULL) { RPC_MEM_FREE(filter, RPC_C_MEM_NSRESOLUTION); } if (msg != NULL) { ldap_msgfree(msg); } if (uuid != NULL) { rpc_string_free(&uuid, status); } }
/* * Create or update an LDAP server binding entry. */ static void rpc_ns__ldap_export_server_element_ext(LDAP *ld, char *dn, rpc_if_handle_t if_spec, rpc_binding_vector_p_t vec, int modop, unsigned32 *status ) { unsigned_char_p_t uuid = NULL; unsigned_char_p_t interfaceID = NULL; rpc_if_id_t if_id; LDAPMod *modV[4]; LDAPMod modRpcNsInterfaceID, modRpcNsBindings, modObjectClass; char **valueRpcNsBindings = NULL; char *valueRpcNsInterfaceID[2], *valueObjectClass[3]; int rc; unsigned i; rpc_if_inq_id(if_spec, &if_id, status); if (*status != rpc_s_ok) { goto out; } /* Get the interface ID */ uuid_to_string(&if_id.uuid, &uuid, status); if (*status != rpc_s_ok) { goto out; } RPC_MEM_ALLOC(interfaceID, unsigned_char_p_t, strlen(uuid) + sizeof(",65535.65535"), RPC_C_MEM_NSRESOLUTION, RPC_C_MEM_WAITOK); sprintf(interfaceID, "%s,%hu.%hu", uuid, if_id.vers_major, if_id.vers_minor); valueRpcNsInterfaceID[0] = interfaceID; valueRpcNsInterfaceID[1] = NULL; modRpcNsInterfaceID.mod_op = LDAP_MOD_ADD; modRpcNsInterfaceID.mod_type = "rpcNsInterfaceID"; modRpcNsInterfaceID.mod_values = valueRpcNsInterfaceID; RPC_MEM_ALLOC(valueRpcNsBindings, char **, (vec->count * sizeof(char *)), RPC_C_MEM_NSRESOLUTION, RPC_C_MEM_WAITOK); memset(valueRpcNsBindings, 0, (vec->count * sizeof(unsigned_char_p_t))); for (i = 0; i < vec->count; i++) { rpc_binding_to_string_binding(vec->binding_h[i], (unsigned_char_p_t *)&valueRpcNsBindings[i], status); if (*status != rpc_s_ok) { goto out; } } valueRpcNsBindings[vec->count] = NULL; modRpcNsBindings.mod_op = modop; modRpcNsBindings.mod_type = "rpcNsBindings"; modRpcNsBindings.mod_values = valueRpcNsBindings; valueObjectClass[0] = "rpcServerElement"; valueObjectClass[1] = "rpcEntry"; valueObjectClass[2] = "top"; modObjectClass.mod_op = modop; modObjectClass.mod_type = "objectClass"; modObjectClass.mod_values = valueObjectClass; modV[0] = &modRpcNsInterfaceID; modV[1] = &modRpcNsBindings; modV[2] = &modObjectClass; modV[3] = NULL; if (modop == LDAP_MOD_ADD) { rc = ldap_add_s(ld, dn, modV); } else { rc = ldap_modify_s(ld, dn, modV); } *status = (rc == LDAP_SUCCESS) ? rpc_s_ok : rpc_s_update_failed; out: if (uuid != NULL) free(uuid); if (interfaceID != NULL) free(interfaceID); if (valueRpcNsBindings != NULL) { char **p; for (p = valueRpcNsBindings; *valueRpcNsBindings != NULL; p++) { unsigned_char_p_t tmp = (unsigned_char_p_t)*p; rpc_string_free(&tmp, status); } RPC_MEM_FREE(valueRpcNsBindings, RPC_C_MEM_NSRESOLUTION); } }
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); }
// Return an appropriate binding for the given ServerName. rpc_binding make_rpc_binding( const char * ServerName, const char * EndPoint) { char * binding_string = NULL; char * endpoint_string = NULL; uint32_t status; if (!EndPoint) { return rpc_binding(); } if (ServerName) { /* add in the "\pipe\" to the endpoint */ asprintf(&endpoint_string, "\\pipe\\%s]", EndPoint); rpc_string_binding_compose(NULL, (idl_char *) "ncacn_np", (idl_char *) ServerName, (idl_char *) endpoint_string, NULL, (idl_char **) &binding_string, &status); if (status != 0) { SMBLogInfo("rpc_string_binding_compose failed on <%s>:<%s> status %#08x", ASL_LEVEL_ERR, ServerName == NULL ? "nullstr" : ServerName, EndPoint == NULL ? "nullstr" : EndPoint, status); /* fallback to the old way instead */ asprintf(&binding_string, "ncacn_np:%s[%s]", ServerName, endpoint_string); } if (endpoint_string != NULL) { free(endpoint_string); } } else { rpc_string_binding_compose(NULL, (idl_char *) "ncalrpc", NULL, (idl_char *) EndPoint, NULL, (idl_char **) &binding_string, &status); if (status != 0) { SMBLogInfo("rpc_string_binding_compose failed on <%s> status %#08x", ASL_LEVEL_ERR, EndPoint == NULL ? "nullstr" : EndPoint, status); /* fallback to the old way instead */ asprintf(&binding_string, "ncalrpc:[%s]", EndPoint); } } if (!binding_string) { platform::invoke_new_handler(); } rpc_binding binding(binding_string); if (status == 0) { /* rpc_string_binding_compose worked */ if (binding_string != NULL) { rpc_string_free((idl_char **) &binding_string, &status); if (status != 0) { SMBLogInfo("rpc_string_free failed on <%s> status %#08x", ASL_LEVEL_ERR, binding_string == NULL ? "nullstr" : binding_string, status); } } } else { /* must have used asprintf */ if (binding_string != NULL) { free(binding_string); } } return binding; }
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); }
PRIVATE void rpc__dg_plog_dump(void) { unsigned16 i; unsigned32 st; static char *lossy_action = "d?r "; /* (0)drop, (1)?, (2)rexmit, (3)normal */ RPC_LOCK_ASSERT(0); if (rpc_g_dg_pkt_log == NULL) { RPC_DBG_PRINTF(rpc_e_dbg_dg_pktlog, 1, ("rpc__dg_plog_dump called, but DG Pkt Logging never enabled\n") ); return; } RPC_DBG_PRINTF(rpc_e_dbg_dg_pktlog, 1, ("tstamp ver ptyp f1 f2 seq/fnum/sn ihnt ahnt len interface/ver/op activity sboot object drep at\n") ); RPC_DBG_PRINTF(rpc_e_dbg_dg_pktlog, 1, ("---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n") ); for (i = 0; i < RPC_C_DG_PKT_LOG_SIZE; i++) { pktlog_elt_p_t p = &rpc_g_dg_pkt_log[i]; unsigned_char_p_t obj, iface, act; rpc_dg_pkt_hdr_p_t hdrp; #ifndef MISPACKED_HDR hdrp = (rpc_dg_pkt_hdr_p_t) &p->hdr; #else hdrp = converted local rep of raw hdr #endif if (p->timestamp == 0) break; dce_uuid_to_string(&hdrp->object, &obj, &st); dce_uuid_to_string(&hdrp->if_id, &iface, &st); dce_uuid_to_string(&hdrp->actuid, &act, &st); RPC_DBG_PRINTF(rpc_e_dbg_dg_pktlog, 1, ("%08x %c%c%1u %-4.4s %02x %02x %08x/%04x/%04x %04x %04x %4d %s/%02u/%03u %s %9u %s %02x%02x%02x %02x\n", p->timestamp, (hdrp->_rpc_vers & 0x80) ? 'R' : lossy_action[p->lossy_action], ((i + 1) % RPC_C_DG_PKT_LOG_SIZE == pkt_log_index) ? '*' : ' ', hdrp->_rpc_vers & 0x7f, rpc__dg_pkt_name(RPC_DG_HDR_INQ_PTYPE(hdrp)), hdrp->flags, hdrp->flags2, hdrp->seq, hdrp->fragnum, hdrp->serial_hi << 8 | hdrp->serial_lo, hdrp->ihint, hdrp->ahint, hdrp->len, iface, hdrp->if_vers, hdrp->opnum, act, hdrp->server_boot, obj, hdrp->drep[0], hdrp->drep[1], hdrp->drep[2], hdrp->auth_proto) ); rpc_string_free(&obj, &st); rpc_string_free(&act, &st); rpc_string_free(&iface, &st); } }
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; }