#include <sys/types.h>
#include <sys/errno.h>
#include <sys/fcntl.h>
#include <time.h>
#include <strings.h>
#include <assert.h>
#include <errno.h>
#include <thread.h>
#include <syslog.h>
#include <synch.h>
#include <libmlrpc/libmlrpc.h>
#include <netsmb/smbfs_api.h>
#include <smbsrv/libsmb.h>
#include <smbsrv/libmlsvc.h>
#include <libsmbrdr.h>
#include <mlsvc.h>
static DWORD
ndr_rpc_bind_common(mlsvc_handle_t *handle, char *server, char *domain,
char *username, const char *service, ndr_auth_ctx_t *auth_ctx)
{
struct smb_ctx *ctx = NULL;
ndr_service_t *svc;
DWORD status;
int rc;
if (handle == NULL || server == NULL || server[0] == '\0' ||
domain == NULL || username == NULL)
return (NT_STATUS_INTERNAL_ERROR);
if ((svc = ndr_svc_lookup_name(service)) == NULL)
return (NT_STATUS_INTERNAL_ERROR);
if (strcmp(username, MLSVC_ANON_USER) == 0)
username = "";
status = smbrdr_ctx_new(&ctx, server, domain, username);
if (status != NT_STATUS_SUCCESS) {
syslog(LOG_ERR, "ndr_rpc_bind: smbrdr_ctx_new"
"(Srv=%s Dom=%s User=%s Svc=%s), %s (0x%x)",
server, domain, username, service,
xlate_nt_status(status), status);
switch (status) {
case NT_STATUS_BAD_NETWORK_PATH:
case NT_STATUS_BAD_NETWORK_NAME:
smb_ddiscover_bad_dc(server);
default:
break;
}
return (status);
}
rc = mlrpc_clh_create(handle, ctx);
if (rc != 0) {
syslog(LOG_ERR, "ndr_rpc_bind: mlrpc_clh_create: rc=%d", rc);
smbrdr_ctx_free(ctx);
switch (rc) {
case ENOMEM:
return (NT_STATUS_NO_MEMORY);
case EINVAL:
return (NT_STATUS_INVALID_PARAMETER);
default:
return (NT_STATUS_INTERNAL_ERROR);
}
}
status = mlrpc_clh_set_auth(handle, auth_ctx);
if (status != 0) {
syslog(LOG_DEBUG, "ndr_rpc_bind: "
"mlrpc_clh_set_auth, %s (0x%x)",
xlate_nt_status(status), status);
goto errout;
}
status = mlrpc_clh_bind(handle, svc);
if (status != 0) {
syslog(LOG_DEBUG, "ndr_rpc_bind: mlrpc_clh_bind"
"(Srv=%s Dom=%s User=%s Svc=%s), %s (0x%x)",
server, domain, username, service,
xlate_nt_status(status), status);
switch (status) {
case RPC_NT_SERVER_TOO_BUSY:
smb_ddiscover_bad_dc(server);
break;
default:
break;
}
goto errout;
}
return (NT_STATUS_SUCCESS);
errout:
ctx = mlrpc_clh_free(handle);
if (ctx != NULL) {
smbrdr_ctx_free(ctx);
}
return (status);
}
DWORD
ndr_rpc_bind(mlsvc_handle_t *handle, char *server, char *domain,
char *username, const char *service)
{
return (ndr_rpc_bind_common(handle, server, domain, username, service,
NULL));
}
DWORD
ndr_rpc_bind_secure(mlsvc_handle_t *handle, char *server, char *domain,
char *username, const char *service, ndr_auth_ctx_t *auth_ctx)
{
return (ndr_rpc_bind_common(handle, server, domain, username, service,
auth_ctx));
}
void
ndr_rpc_unbind(mlsvc_handle_t *handle)
{
struct smb_ctx *ctx;
ctx = mlrpc_clh_free(handle);
if (ctx != NULL)
smbrdr_ctx_free(ctx);
bzero(handle, sizeof (mlsvc_handle_t));
}
void
ndr_rpc_status(mlsvc_handle_t *handle, int opnum, DWORD status)
{
ndr_service_t *svc;
char *name = "NDR RPC";
char *s = "unknown";
switch (NT_SC_SEVERITY(status)) {
case NT_STATUS_SEVERITY_SUCCESS:
s = "success";
break;
case NT_STATUS_SEVERITY_INFORMATIONAL:
s = "info";
break;
case NT_STATUS_SEVERITY_WARNING:
s = "warning";
break;
case NT_STATUS_SEVERITY_ERROR:
s = "error";
break;
}
if (handle) {
svc = handle->clnt->binding->service;
name = svc->name;
}
smb_tracef("%s[0x%02x]: %s: %s (0x%08x)",
name, opnum, s, xlate_nt_status(status), status);
}