/**************************************************************************** Make a connection, given the snum to connect to, and the vuser of the connecting user if appropriate. Does note invoke the NTVFS connection hook ****************************************************************************/ 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; uint64_t ntvfs_caps = 0; 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; if (req->smb_conn->negotiate.client_caps & CAP_LEVEL_II_OPLOCKS) { ntvfs_caps |= NTVFS_CLIENT_CAP_LEVEL_II_OPLOCKS; } /* init ntvfs function pointers */ status = ntvfs_init_connection(tcon, scfg, type, req->smb_conn->negotiate.protocol, ntvfs_caps, req->smb_conn->connection->event.ctx, req->smb_conn->connection->msg_ctx, req->smb_conn->lp_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; } return NT_STATUS_OK; failed: req->tcon = NULL; talloc_free(tcon); return status; }
/**************************************************************************** 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; }