/* * 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); }
/* * 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); }