NTSTATUS srvsvc_create_ntvfs_context(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, const char *share, struct ntvfs_context **_ntvfs) { NTSTATUS status; struct srvsvc_ntvfs_ctx *c; struct ntvfs_request *ntvfs_req; enum ntvfs_type type; struct share_context *sctx; struct share_config *scfg; const char *sharetype; union smb_tcon tcon; const struct tsocket_address *local_address; const struct tsocket_address *remote_address; status = share_get_context_by_name(mem_ctx, lpcfg_share_backend(dce_call->conn->dce_ctx->lp_ctx), dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx); if (!NT_STATUS_IS_OK(status)) { return status; } status = share_get_config(mem_ctx, sctx, share, &scfg); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("srvsvc_create_ntvfs_context: couldn't find service %s\n", share)); return status; } #if 0 /* TODO: fix access cecking */ if (!socket_check_access(dce_call->connection->socket, scfg->name, share_string_list_option(scfg, SHARE_HOSTS_ALLOW), share_string_list_option(scfg, SHARE_HOSTS_DENY))) { return NT_STATUS_ACCESS_DENIED; } #endif /* work out what sort of connection this is */ sharetype = share_string_option(scfg, SHARE_TYPE, SHARE_TYPE_DEFAULT); if (sharetype && strcmp(sharetype, "IPC") == 0) { type = NTVFS_IPC; } else if (sharetype && strcmp(sharetype, "PRINTER")) { type = NTVFS_PRINT; } else { type = NTVFS_DISK; } c = talloc(mem_ctx, struct srvsvc_ntvfs_ctx); NT_STATUS_HAVE_NO_MEMORY(c); /* init ntvfs function pointers */ status = ntvfs_init_connection(c, scfg, type, PROTOCOL_NT1, 0,/* ntvfs_client_caps */ dce_call->event_ctx, dce_call->conn->msg_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->server_id, &c->ntvfs); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("srvsvc_create_ntvfs_context: ntvfs_init_connection failed for service %s\n", scfg->name)); return status; } talloc_set_destructor(c, srvsvc_ntvfs_ctx_destructor); /* * NOTE: we only set the addr callbacks as we're not interesseted in oplocks or in getting file handles */ local_address = dcesrv_connection_get_local_address(dce_call->conn); remote_address = dcesrv_connection_get_remote_address(dce_call->conn); status = ntvfs_set_addresses(c->ntvfs, local_address, remote_address); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("srvsvc_create_ntvfs_context: NTVFS failed to set the addr callbacks!\n")); return status; } ntvfs_req = ntvfs_request_create(c->ntvfs, mem_ctx, dce_call->conn->auth_state.session_info, 0, /* TODO: fill in PID */ dce_call->time, NULL, NULL, 0); NT_STATUS_HAVE_NO_MEMORY(ntvfs_req); /* Invoke NTVFS connection hook */ tcon.tcon.level = RAW_TCON_TCON; ZERO_STRUCT(tcon.tcon.in); tcon.tcon.in.service = scfg->name; status = ntvfs_connect(ntvfs_req, &tcon); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("srvsvc_create_ntvfs_context: NTVFS ntvfs_connect() failed!\n")); return status; } *_ntvfs = c->ntvfs; return NT_STATUS_OK; }
/**************************************************************************** Make a connection, given the snum to connect to, and the vuser of the connecting user if appropriate. ****************************************************************************/ static NTSTATUS make_connection_scfg(struct smbsrv_request *req, struct share_config *scfg, enum ntvfs_type type, DATA_BLOB password, const char *dev) { struct smbsrv_tcon *tcon; NTSTATUS status; tcon = smbsrv_smb_tcon_new(req->smb_conn, scfg->name); if (!tcon) { DEBUG(0,("Couldn't find free connection.\n")); return NT_STATUS_INSUFFICIENT_RESOURCES; } req->tcon = tcon; /* init ntvfs function pointers */ status = ntvfs_init_connection(tcon, scfg, type, req->smb_conn->negotiate.protocol, req->smb_conn->connection->event.ctx, req->smb_conn->connection->msg_ctx, req->smb_conn->connection->server_id, &tcon->ntvfs); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("make_connection_scfg: connection failed for service %s\n", scfg->name)); goto failed; } status = ntvfs_set_oplock_handler(tcon->ntvfs, smbsrv_send_oplock_break, tcon); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("make_connection: NTVFS failed to set the oplock handler!\n")); goto failed; } status = ntvfs_set_addr_callbacks(tcon->ntvfs, smbsrv_get_my_addr, smbsrv_get_peer_addr, req->smb_conn); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("make_connection: NTVFS failed to set the addr callbacks!\n")); goto failed; } status = ntvfs_set_handle_callbacks(tcon->ntvfs, smbsrv_handle_create_new, smbsrv_handle_make_valid, smbsrv_handle_destroy, smbsrv_handle_search_by_wire_key, smbsrv_handle_get_wire_key, tcon); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("make_connection: NTVFS failed to set the handle callbacks!\n")); goto failed; } req->ntvfs = ntvfs_request_create(req->tcon->ntvfs, req, req->session->session_info, SVAL(req->in.hdr,HDR_PID), req->request_time, req, NULL, 0); if (!req->ntvfs) { status = NT_STATUS_NO_MEMORY; goto failed; } /* Invoke NTVFS connection hook */ status = ntvfs_connect(req->ntvfs, scfg->name); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("make_connection: NTVFS make connection failed!\n")); goto failed; } return NT_STATUS_OK; failed: req->tcon = NULL; talloc_free(tcon); return status; }
static NTSTATUS smb2srv_tcon_backend(struct smb2srv_request *req, union smb_tcon *io) { struct smbsrv_tcon *tcon; NTSTATUS status; enum ntvfs_type type; uint16_t type_smb2; uint32_t unknown2; const char *service = io->smb2.in.path; struct share_config *scfg; const char *sharetype; if (strncmp(service, "\\\\", 2) == 0) { const char *p = strchr(service+2, '\\'); if (p) { service = p + 1; } } status = share_get_config(req, req->smb_conn->share_context, service, &scfg); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("smb2srv_tcon_backend: couldn't find service %s\n", service)); return NT_STATUS_BAD_NETWORK_NAME; } if (!socket_check_access(req->smb_conn->connection->socket, scfg->name, share_string_list_option(req, scfg, SHARE_HOSTS_ALLOW), share_string_list_option(req, scfg, SHARE_HOSTS_DENY))) { return NT_STATUS_ACCESS_DENIED; } /* work out what sort of connection this is */ sharetype = share_string_option(scfg, SHARE_TYPE, "DISK"); if (sharetype && strcmp(sharetype, "IPC") == 0) { type = NTVFS_IPC; type_smb2 = 0x0002; unknown2 = 0x00000030; } else if (sharetype && strcmp(sharetype, "PRINTER") == 0) { type = NTVFS_PRINT; type_smb2 = 0x0003; unknown2 = 0x00000000; } else { type = NTVFS_DISK; type_smb2 = 0x0001; unknown2 = 0x00000800; } tcon = smbsrv_smb2_tcon_new(req->session, scfg->name); if (!tcon) { DEBUG(0,("smb2srv_tcon_backend: Couldn't find free connection.\n")); return NT_STATUS_INSUFFICIENT_RESOURCES; } req->tcon = tcon; /* init ntvfs function pointers */ status = ntvfs_init_connection(tcon, scfg, type, req->smb_conn->negotiate.protocol, req->smb_conn->connection->event.ctx, req->smb_conn->connection->msg_ctx, req->smb_conn->connection->server_id, &tcon->ntvfs); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("smb2srv_tcon_backend: ntvfs_init_connection failed for service %s\n", scfg->name)); goto failed; } status = ntvfs_set_oplock_handler(tcon->ntvfs, smb2srv_send_oplock_break, tcon); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("smb2srv_tcon_backend: NTVFS failed to set the oplock handler!\n")); goto failed; } status = ntvfs_set_addr_callbacks(tcon->ntvfs, smbsrv_get_my_addr, smbsrv_get_peer_addr, req->smb_conn); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("smb2srv_tcon_backend: NTVFS failed to set the addr callbacks!\n")); goto failed; } status = ntvfs_set_handle_callbacks(tcon->ntvfs, smb2srv_handle_create_new, smb2srv_handle_make_valid, smb2srv_handle_destroy, smb2srv_handle_search_by_wire_key, smb2srv_handle_get_wire_key, tcon); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("smb2srv_tcon_backend: NTVFS failed to set the handle callbacks!\n")); goto failed; } req->ntvfs = ntvfs_request_create(req->tcon->ntvfs, req, req->session->session_info, 0, /* TODO: fill in PID */ req->request_time, req, NULL, 0); if (!req->ntvfs) { status = NT_STATUS_NO_MEMORY; goto failed; } /* Invoke NTVFS connection hook */ status = ntvfs_connect(req->ntvfs, scfg->name); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("smb2srv_tcon_backend: NTVFS ntvfs_connect() failed!\n")); goto failed; } io->smb2.out.unknown1 = type_smb2; /* 1 - DISK, 2 - Print, 3 - IPC */ io->smb2.out.unknown2 = unknown2; io->smb2.out.unknown3 = 0x00000000; io->smb2.out.access_mask= SEC_RIGHTS_FILE_ALL; io->smb2.out.tid = tcon->tid; return NT_STATUS_OK; failed: req->tcon = NULL; talloc_free(tcon); return status; }