示例#1
0
/*
 * smbrdr_logon
 *
 * I'm not sure this really needs to do anything, but for now
 * let's go ahead and authenticate here so this can return a
 * status reflecting the outcome of authentication.
 *
 * If this successfully builds an smb_ctx, it just frees it.
 * The driver retains sessions for a little while after the
 * last reference goes away, so the session created here will
 * usually still exist when the next call to smbrdr_ctx_new
 * asks for this server+user (immediately after this returns),
 * and only one session setup will go over the wire.
 */
int
smbrdr_logon(char *srv, char *dom, char *user)
{
	struct smb_ctx *ctx;
	int err;

	err = smbrdr_ctx_new(&ctx, srv, dom, user);
	if (err == 0)
		smb_ctx_free(ctx);
	return (err);
}
示例#2
0
/*
 * This call must be made to initialize an RPC client structure and bind
 * to the remote service before any RPCs can be exchanged with that service.
 *
 * The mlsvc_handle_t is a wrapper that is used to associate an RPC handle
 * with the client context for an instance of the interface.  The handle
 * is zeroed to ensure that it doesn't look like a valid handle -
 * handle content is provided by the remove service.
 *
 * The client points to this top-level handle so that we know when to
 * unbind and teardown the connection.  As each handle is initialized it
 * will inherit a reference to the client context.
 *
 * Returns 0 or an NT_STATUS:
 *	NT_STATUS_BAD_NETWORK_PATH	(get server addr)
 *	NT_STATUS_NETWORK_ACCESS_DENIED	(connect, auth)
 *	NT_STATUS_BAD_NETWORK_NAME	(tcon, open)
 *	NT_STATUS_ACCESS_DENIED		(open pipe)
 *	NT_STATUS_INVALID_PARAMETER	(rpc bind)
 *
 *	NT_STATUS_INTERNAL_ERROR	(bad args etc)
 *	NT_STATUS_NO_MEMORY
 */
DWORD
ndr_rpc_bind(mlsvc_handle_t *handle, char *server, char *domain,
    char *username, const char *service)
{
	struct smb_ctx		*ctx = NULL;
	ndr_client_t		*clnt = NULL;
	ndr_service_t		*svc;
	srvsvc_server_info_t	svinfo;
	DWORD			status;
	int			fd = -1;
	int			rc;

	if (handle == NULL || server == NULL || server[0] == '\0' ||
	    domain == NULL || username == NULL)
		return (NT_STATUS_INTERNAL_ERROR);

	/* In case the service was not registered... */
	if ((svc = ndr_svc_lookup_name(service)) == NULL)
		return (NT_STATUS_INTERNAL_ERROR);

	/*
	 * Set the default based on the assumption that most
	 * servers will be Windows 2000 or later.  This used to
	 * try to get the actual server version, but that RPC
	 * is not necessarily allowed anymore, so don't bother.
	 */
	bzero(&svinfo, sizeof (srvsvc_server_info_t));
	svinfo.sv_platform_id = SV_PLATFORM_ID_NT;
	svinfo.sv_version_major = 5;
	svinfo.sv_version_minor = 0;
	svinfo.sv_type = SV_TYPE_DEFAULT;
	svinfo.sv_os = NATIVE_OS_WIN2000;

	/*
	 * Some callers pass this when they want a NULL session.
	 * Todo: have callers pass an empty string for that.
	 */
	if (strcmp(username, MLSVC_ANON_USER) == 0)
		username = "";

	/*
	 * Setup smbfs library handle, authenticate, connect to
	 * the IPC$ share.  This will reuse an existing connection
	 * if the driver already has one for this combination of
	 * server, user, domain.  It may return any of:
	 *	NT_STATUS_BAD_NETWORK_PATH	(get server addr)
	 *	NT_STATUS_NETWORK_ACCESS_DENIED	(connect, auth)
	 *	NT_STATUS_BAD_NETWORK_NAME	(tcon)
	 */
	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), %s (0x%x)",
		    server, domain, username,
		    xlate_nt_status(status), status);
		/* Tell the DC Locator this DC failed. */
		smb_ddiscover_bad_dc(server);
		goto errout;
	}

	/*
	 * Open the named pipe.
	 */
	fd = smb_fh_open(ctx, svc->endpoint, O_RDWR);
	if (fd < 0) {
		rc = errno;
		syslog(LOG_DEBUG, "ndr_rpc_bind: "
		    "smb_fh_open (%s) err=%d",
		    svc->endpoint, rc);
		switch (rc) {
		case EACCES:
			status = NT_STATUS_ACCESS_DENIED;
			break;
		default:
			status = NT_STATUS_BAD_NETWORK_NAME;
			break;
		}
		goto errout;
	}

	/*
	 * Setup the RPC client handle.
	 */
	if ((clnt = malloc(sizeof (ndr_client_t))) == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto errout;
	}
	bzero(clnt, sizeof (ndr_client_t));

	clnt->handle = &handle->handle;
	clnt->xa_init = ndr_xa_init;
	clnt->xa_exchange = ndr_xa_exchange;
	clnt->xa_read = ndr_xa_read;
	clnt->xa_preserve = ndr_xa_preserve;
	clnt->xa_destruct = ndr_xa_destruct;
	clnt->xa_release = ndr_xa_release;
	clnt->xa_private = ctx;
	clnt->xa_fd = fd;

	ndr_svc_binding_pool_init(&clnt->binding_list,
	    clnt->binding_pool, NDR_N_BINDING_POOL);

	if ((clnt->heap = ndr_heap_create()) == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto errout;
	}

	/*
	 * Fill in the caller's handle.
	 */
	bzero(&handle->handle, sizeof (ndr_hdid_t));
	handle->clnt = clnt;
	bcopy(&svinfo, &handle->svinfo, sizeof (srvsvc_server_info_t));

	/*
	 * Do the OtW RPC bind.
	 */
	rc = ndr_clnt_bind(clnt, service, &clnt->binding);
	switch (rc) {
	case NDR_DRC_FAULT_OUT_OF_MEMORY:
		status = NT_STATUS_NO_MEMORY;
		break;
	case NDR_DRC_FAULT_API_SERVICE_INVALID:	/* not registered */
		status = NT_STATUS_INTERNAL_ERROR;
		break;
	default:
		if (NDR_DRC_IS_FAULT(rc)) {
			status = NT_STATUS_INVALID_PARAMETER;
			break;
		}
		/* FALLTHROUGH */
	case NDR_DRC_OK:
		return (NT_STATUS_SUCCESS);
	}

	syslog(LOG_DEBUG, "ndr_rpc_bind: "
	    "ndr_clnt_bind, %s (0x%x)",
	    xlate_nt_status(status), status);

errout:
	handle->clnt = NULL;
	if (clnt != NULL) {
		ndr_heap_destroy(clnt->heap);
		free(clnt);
	}
	if (ctx != NULL) {
		if (fd != -1)
			(void) smb_fh_close(fd);
		smbrdr_ctx_free(ctx);
	}

	return (status);
}