The branch, v4-7-test has been updated via af47cdb s3:smbd: Do not crash if we fail to init the session table via 1efaec6 libsmb: Use smb2 tcon if conn_protocol >= SMB2_02 via e8a69b9 torture: Add test for channel sequence number handling via 164b38c smbXcli: Add "force_channel_sequence" via f2d311e smbd: Fix channel sequence number checks for long-running requests via d5c0ad6 smbd: Remove a "!" from an if-condition for easier readability via caca68c torture4: Fix typos via 09200da smbd: Fix a typo from b276495 build: fix libceph-common detection
https://git.samba.org/?p=samba.git;a=shortlog;h=v4-7-test - Log ----------------------------------------------------------------- commit af47cdb3e1310ba0a365fa2c5b0161b6554fbead Author: Andreas Schneider <a...@samba.org> Date: Mon Feb 19 18:07:50 2018 +0100 s3:smbd: Do not crash if we fail to init the session table This should the following segfault with SMB1: #6 sig_fault (sig=<optimized out>) at ../lib/util/fault.c:94 #7 <signal handler called> #8 smbXsrv_session_create (conn=conn@entry=0x5654d3512af0, now=now@entry=131594481900356690, _session=_session@entry=0x7ffc93a778e8) at ../source3/smbd/smbXsrv_session.c:1212 #9 0x00007f7618aa21ef in reply_sesssetup_and_X (req=req@entry=0x5654d35174b0) at ../source3/smbd/sesssetup.c:961 #10 0x00007f7618ae17b0 in switch_message (type=<optimized out>, req=req@entry=0x5654d35174b0) at ../source3/smbd/process.c:1726 #11 0x00007f7618ae3550 in construct_reply (deferred_pcd=0x0, encrypted=false, seqnum=0, unread_bytes=0, size=140, inbuf=0x0, xconn=0x5654d35146d0) at ../source3/smbd/process.c:1762 #12 process_smb (xconn=xconn@entry=0x5654d3512af0, inbuf=<optimized out>, nread=140, unread_bytes=0, seqnum=0, encrypted=<optimized out>, deferred_pcd=deferred_pcd@entry=0x0) at ../source3/smbd/process.c:2008 #13 0x00007f7618ae4c41 in smbd_server_connection_read_handler (xconn=0x5654d3512af0, fd=40) at ../source3/smbd/process.c:2608 #14 0x00007f761587eedb in epoll_event_loop_once () from /lib64/libtevent.so.0 Inspection the core shows that: conn->client-session_table is NULL conn->protocol is PROTOCOL_NONE BUG: https://bugzilla.samba.org/show_bug.cgi?id=13315 Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> (cherry picked from commit a89a7146563f2d9eb8bc02f1c090158ee499c878) Autobuild-User(v4-7-test): Stefan Metzmacher <me...@samba.org> Autobuild-Date(v4-7-test): Thu Mar 8 17:53:27 CET 2018 on sn-devel-144 commit 1efaec6bc9f51e3595ed254e38b6569962d36ee4 Author: Dan Robertson <drobert...@tripwire.com> Date: Thu Feb 22 20:47:11 2018 +0000 libsmb: Use smb2 tcon if conn_protocol >= SMB2_02 When the connection protocol is SMB2 the tid from the smb1 member is used instead of smb2 in cli_state_set_tid which often results in a null deref. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13310 Signed-off-by: Dan Robertson <drobert...@tripwire.com> Reviewed-by: Jeremy Allison <j...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> (cherry picked from commit b67ffaf518c971817b167b41bf6226cddfdcfd2f) commit e8a69b9a3a58de4d78be1fabe7c5263002528a47 Author: Volker Lendecke <v...@samba.org> Date: Thu Jan 11 11:55:39 2018 +0100 torture: Add test for channel sequence number handling We run into an assert when the csn wraps Bug: https://bugzilla.samba.org/show_bug.cgi?id=13215 Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> Autobuild-User(master): Stefan Metzmacher <me...@samba.org> Autobuild-Date(master): Sun Jan 14 14:47:15 CET 2018 on sn-devel-144 (cherry picked from commit 0abe16a5343de9a69bb5cccbad9809b28b642f45) commit 164b38ccb778a9128fd6ad29cad72ab96e109f9d Author: Volker Lendecke <v...@samba.org> Date: Thu Jan 11 11:25:49 2018 +0100 smbXcli: Add "force_channel_sequence" This enables use of the channel sequence number even for non-multi-channel servers. This makes our client invalid, but we need to protect against broken clients with tests. Bug: https://bugzilla.samba.org/show_bug.cgi?id=13215 Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit cd288a08500b1cc38ef26e5cb8ef754b4da658b6) commit f2d311eee9301717b99ed7ae758f0d05958d86b0 Author: Volker Lendecke <v...@samba.org> Date: Thu Jan 11 15:34:45 2018 +0100 smbd: Fix channel sequence number checks for long-running requests When the client's supplied csn overflows and hits a pending, long-running request's csn, we panic. Fix this by counting the overflows in smbXsrv_open_global0->channel_generation Bug: https://bugzilla.samba.org/show_bug.cgi?id=13215 Pair-Programmed-With: Stefan Metzmacher <me...@samba.org> Signed-off-by: Volker Lendecke <v...@samba.org> Signed-off-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit 0b57434151a8334a6e9b9b7542824ce4915421a2) commit d5c0ad63c942f4df60ef6dfcee5c48c65ba7dea3 Author: Volker Lendecke <v...@samba.org> Date: Wed Jan 10 14:59:08 2018 +0100 smbd: Remove a "!" from an if-condition for easier readability Bug: https://bugzilla.samba.org/show_bug.cgi?id=13215 Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit 03f65a7cdc91091a171269cfebc9916f2f678388) commit caca68c233f63a5ce3968c8bf8444aff9ac62479 Author: Volker Lendecke <v...@samba.org> Date: Wed Jan 10 15:51:56 2018 +0100 torture4: Fix typos Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit 71cee27962cba53da3249bd3f5ece32a1d10071d) commit 09200da7f28d0764022c4fc8db02d70e4bd37bb0 Author: Volker Lendecke <v...@samba.org> Date: Wed Jan 10 14:29:01 2018 +0100 smbd: Fix a typo Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit e8636e7ab75f89e89ef054b5d4aa6c07fddcbe2a) ----------------------------------------------------------------------- Summary of changes: libcli/smb/smbXcli_base.c | 15 +++++- libcli/smb/smbXcli_base.h | 4 ++ source3/librpc/idl/smbXsrv.idl | 3 +- source3/libsmb/clientgen.c | 2 +- source3/smbd/globals.h | 1 + source3/smbd/negprot.c | 23 ++++++-- source3/smbd/smb2_server.c | 27 +++++++--- source4/torture/smb2/replay.c | 117 +++++++++++++++++++++++++++++++++++++---- 8 files changed, 169 insertions(+), 23 deletions(-) Changeset truncated at 500 lines: diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c index 7322380..f1f90d9 100644 --- a/libcli/smb/smbXcli_base.c +++ b/libcli/smb/smbXcli_base.c @@ -138,6 +138,8 @@ struct smbXcli_conn { uint8_t io_priority; + bool force_channel_sequence; + uint8_t preauth_sha512[64]; } smb2; @@ -549,6 +551,17 @@ const struct GUID *smbXcli_conn_server_guid(struct smbXcli_conn *conn) return &conn->smb1.server.guid; } +bool smbXcli_conn_get_force_channel_sequence(struct smbXcli_conn *conn) +{ + return conn->smb2.force_channel_sequence; +} + +void smbXcli_conn_set_force_channel_sequence(struct smbXcli_conn *conn, + bool v) +{ + conn->smb2.force_channel_sequence = v; +} + struct smbXcli_conn_samba_suicide_state { struct smbXcli_conn *conn; struct iovec iov; @@ -2899,7 +2912,7 @@ struct tevent_req *smb2cli_req_create(TALLOC_CTX *mem_ctx, uint32_t flags = 0; uint32_t tid = 0; uint64_t uid = 0; - bool use_channel_sequence = false; + bool use_channel_sequence = conn->smb2.force_channel_sequence; uint16_t channel_sequence = 0; bool use_replay_flag = false; diff --git a/libcli/smb/smbXcli_base.h b/libcli/smb/smbXcli_base.h index 6d9198a..2532084 100644 --- a/libcli/smb/smbXcli_base.h +++ b/libcli/smb/smbXcli_base.h @@ -59,6 +59,10 @@ uint16_t smbXcli_conn_max_requests(struct smbXcli_conn *conn); NTTIME smbXcli_conn_server_system_time(struct smbXcli_conn *conn); const DATA_BLOB *smbXcli_conn_server_gss_blob(struct smbXcli_conn *conn); const struct GUID *smbXcli_conn_server_guid(struct smbXcli_conn *conn); +bool smbXcli_conn_get_force_channel_sequence(struct smbXcli_conn *conn); +void smbXcli_conn_set_force_channel_sequence(struct smbXcli_conn *conn, + bool v); + struct tevent_req *smbXcli_conn_samba_suicide_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl index 1bfa51e..d3f8d30 100644 --- a/source3/librpc/idl/smbXsrv.idl +++ b/source3/librpc/idl/smbXsrv.idl @@ -430,7 +430,8 @@ interface smbXsrv uint32 durable_timeout_msec; boolean8 durable; DATA_BLOB backend_cookie; - hyper channel_sequence; + uint16 channel_sequence; + hyper channel_generation; } smbXsrv_open_global0; typedef union { diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 44afee1..2e4dd15 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -371,7 +371,7 @@ uint32_t cli_state_set_tid(struct cli_state *cli, uint32_t tid) uint32_t ret; if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { ret = smb2cli_tcon_current_id(cli->smb2.tcon); - smb2cli_tcon_set_id(cli->smb1.tcon, tid); + smb2cli_tcon_set_id(cli->smb2.tcon, tid); } else { ret = smb1cli_tcon_current_id(cli->smb1.tcon); smb1cli_tcon_set_id(cli->smb1.tcon, tid); diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 78f1260..69db07a 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -744,6 +744,7 @@ struct smbd_smb2_request { * adapted again in reply. */ bool request_counters_updated; + uint64_t channel_generation; /* * The sub request for async backend calls. diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index d3f4776..70249f7 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -65,6 +65,8 @@ static void reply_lanman1(struct smb_request *req, uint16_t choice) time_t t = time(NULL); struct smbXsrv_connection *xconn = req->xconn; uint16_t raw; + NTSTATUS status; + if (lp_async_smb_echo_handler()) { raw = 0; } else { @@ -88,7 +90,11 @@ static void reply_lanman1(struct smb_request *req, uint16_t choice) SSVAL(req->outbuf,smb_vwv11, 8); } - smbXsrv_connection_init_tables(xconn, PROTOCOL_LANMAN1); + status = smbXsrv_connection_init_tables(xconn, PROTOCOL_LANMAN1); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + return; + } /* Reply, SMBlockread, SMBwritelock supported. */ SCVAL(req->outbuf,smb_flg, FLAG_REPLY|FLAG_SUPPORT_LOCKREAD); @@ -115,6 +121,8 @@ static void reply_lanman2(struct smb_request *req, uint16_t choice) time_t t = time(NULL); struct smbXsrv_connection *xconn = req->xconn; uint16_t raw; + NTSTATUS status; + if (lp_async_smb_echo_handler()) { raw = 0; } else { @@ -140,7 +148,11 @@ static void reply_lanman2(struct smb_request *req, uint16_t choice) SSVAL(req->outbuf,smb_vwv11, 8); } - smbXsrv_connection_init_tables(xconn, PROTOCOL_LANMAN2); + status = smbXsrv_connection_init_tables(xconn, PROTOCOL_LANMAN2); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + return; + } /* Reply, SMBlockread, SMBwritelock supported. */ SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD); @@ -260,6 +272,7 @@ static void reply_nt1(struct smb_request *req, uint16_t choice) struct smbXsrv_connection *xconn = req->xconn; bool signing_desired = false; bool signing_required = false; + NTSTATUS status; xconn->smb1.negprot.encrypted_passwords = lp_encrypt_passwords(); @@ -337,7 +350,11 @@ static void reply_nt1(struct smb_request *req, uint16_t choice) SSVAL(req->outbuf,smb_vwv0,choice); SCVAL(req->outbuf,smb_vwv1,secword); - smbXsrv_connection_init_tables(xconn, PROTOCOL_NT1); + status = smbXsrv_connection_init_tables(xconn, PROTOCOL_NT1); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + return; + } SSVAL(req->outbuf,smb_vwv1+1, lp_max_mux()); /* maxmpx */ SSVAL(req->outbuf,smb_vwv2+1, 1); /* num vcs */ diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 5290c05..a731880 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -2158,6 +2158,7 @@ static NTSTATUS smbd_smb2_request_dispatch_update_counts( struct smbXsrv_connection *xconn = req->xconn; const uint8_t *inhdr; uint16_t channel_sequence; + uint8_t generation_wrap = 0; uint32_t flags; int cmp; struct smbXsrv_open *op; @@ -2184,6 +2185,14 @@ static NTSTATUS smbd_smb2_request_dispatch_update_counts( channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE); cmp = channel_sequence - op->global->channel_sequence; + if (cmp < 0) { + /* + * csn wrap. We need to watch out for long-running + * requests that are still sitting on a previously + * used csn. SMB2_OP_NOTIFY can take VERY long. + */ + generation_wrap += 1; + } if (abs(cmp) > INT16_MAX) { /* @@ -2220,7 +2229,7 @@ static NTSTATUS smbd_smb2_request_dispatch_update_counts( * a 16 bit overflow of the client-submitted sequence * number: * - * If the stored channel squence number is more than + * If the stored channel sequence number is more than * 0x7FFF larger than the one from the request, then * the client-provided sequence number has likely * overflown. We treat this case as valid instead @@ -2231,33 +2240,36 @@ static NTSTATUS smbd_smb2_request_dispatch_update_counts( cmp *= -1; } - if (!(flags & SMB2_HDR_FLAG_REPLAY_OPERATION)) { - if (cmp == 0) { + if (flags & SMB2_HDR_FLAG_REPLAY_OPERATION) { + if (cmp == 0 && op->pre_request_count == 0) { op->request_count += 1; req->request_counters_updated = true; - } else if (cmp > 0) { + } else if (cmp > 0 && op->pre_request_count == 0) { op->pre_request_count += op->request_count; op->request_count = 1; op->global->channel_sequence = channel_sequence; + op->global->channel_generation += generation_wrap; update_open = true; req->request_counters_updated = true; } else if (modify_call) { return NT_STATUS_FILE_NOT_AVAILABLE; } } else { - if (cmp == 0 && op->pre_request_count == 0) { + if (cmp == 0) { op->request_count += 1; req->request_counters_updated = true; - } else if (cmp > 0 && op->pre_request_count == 0) { + } else if (cmp > 0) { op->pre_request_count += op->request_count; op->request_count = 1; op->global->channel_sequence = channel_sequence; + op->global->channel_generation += generation_wrap; update_open = true; req->request_counters_updated = true; } else if (modify_call) { return NT_STATUS_FILE_NOT_AVAILABLE; } } + req->channel_generation = op->global->channel_generation; if (update_open) { status = smbXsrv_open_update(op); @@ -2744,7 +2756,8 @@ static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req) inhdr = SMBD_SMB2_IN_HDR_PTR(req); channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE); - if (op->global->channel_sequence == channel_sequence) { + if ((op->global->channel_sequence == channel_sequence) && + (op->global->channel_generation == req->channel_generation)) { SMB_ASSERT(op->request_count > 0); op->request_count -= 1; } else { diff --git a/source4/torture/smb2/replay.c b/source4/torture/smb2/replay.c index a38518a..021346a 100644 --- a/source4/torture/smb2/replay.c +++ b/source4/torture/smb2/replay.c @@ -473,7 +473,7 @@ done: } /** - * Test Durablity V2 Create Replay Detection on Single Channel. + * Test Durability V2 Create Replay Detection on Single Channel. */ static bool test_replay_dhv2_oplock1(struct torture_context *tctx, struct smb2_tree *tree) @@ -560,7 +560,7 @@ done: } /** - * Test Durablity V2 Create Replay Detection on Single Channel. + * Test Durability V2 Create Replay Detection on Single Channel. * Hand in a different oplock level in the replay. * Server responds with the handed in oplock level and * corresponding durable status, but does not change the @@ -697,7 +697,7 @@ done: } /** - * Test Durablity V2 Create Replay Detection on Single Channel. + * Test Durability V2 Create Replay Detection on Single Channel. * Replay with a different share mode. The share mode of * the opened file is not changed by this. */ @@ -823,7 +823,7 @@ done: } /** - * Test Durablity V2 Create Replay Detection on Single Channel. + * Test Durability V2 Create Replay Detection on Single Channel. * Create with an oplock, and replay with a lease. */ static bool test_replay_dhv2_oplock_lease(struct torture_context *tctx, @@ -927,7 +927,7 @@ done: /** - * Test durablity v2 create replay detection on single channel. + * Test durability v2 create replay detection on single channel. * Variant with leases instead of oplocks: * - open a file with a rh lease * - upgrade to a rwh lease with a second create @@ -1065,7 +1065,7 @@ done: } /** - * Test durablity v2 create replay detection on single channel. + * Test durability v2 create replay detection on single channel. * Variant with leases instead of oplocks, where the * replay does not specify the original lease level but * just a "R" lease. This still gives the upgraded lease @@ -1216,7 +1216,7 @@ done: } /** - * Test durablity v2 create replay detection on single channel. + * Test durability v2 create replay detection on single channel. * create with a lease, and replay with a different lease key */ static bool test_replay_dhv2_lease3(struct torture_context *tctx, @@ -1349,7 +1349,7 @@ done: } /** - * Test durablity v2 create replay detection on single channel. + * Test durability v2 create replay detection on single channel. * Do the original create with a lease, and do the replay * with an oplock. */ @@ -1758,7 +1758,7 @@ done: } /** - * Test Durablity V2 Create Replay Detection on Multi Channel + * Test Durability V2 Create Replay Detection on Multi Channel */ static bool test_replay3(struct torture_context *tctx, struct smb2_tree *tree1) { @@ -2162,7 +2162,7 @@ done: } /** - * Test Durablity V2 Persistent Create Replay on a Single Channel + * Test Durability V2 Persistent Create Replay on a Single Channel */ static bool test_replay5(struct torture_context *tctx, struct smb2_tree *tree) { @@ -2425,6 +2425,102 @@ done: return ret; } +static bool test_replay7(struct torture_context *tctx, struct smb2_tree *tree) +{ + TALLOC_CTX *mem_ctx = talloc_new(tctx); + struct smb2_transport *transport = tree->session->transport; + NTSTATUS status; + struct smb2_handle _dh; + struct smb2_handle *dh = NULL; + struct smb2_notify notify; + struct smb2_request *req; + union smb_fileinfo qfinfo; + bool ret = false; + + if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) { + torture_skip(tctx, "SMB 3.X Dialect family required for " + "replay tests\n"); + } + + torture_comment(tctx, "Notify across increment/decrement of csn\n"); + + smbXcli_conn_set_force_channel_sequence(transport->conn, true); + + status = torture_smb2_testdir(tree, BASEDIR, &_dh); + CHECK_STATUS(status, NT_STATUS_OK); + dh = &_dh; + + notify.in.recursive = 0x0000; + notify.in.buffer_size = 0xffff; + notify.in.file.handle = _dh; + notify.in.completion_filter = FILE_NOTIFY_CHANGE_FILE_NAME; + notify.in.unknown = 0x00000000; + + /* + * This posts a long-running request with csn==0 to "dh". Now + * op->request_count==1 in smb2_server.c. + */ + smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 0); + req = smb2_notify_send(tree, ¬ify); + + qfinfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_POSITION_INFORMATION, + .generic.in.file.handle = _dh + }; + + /* + * This sequence of 2 dummy requests moves + * op->request_count==1 to op->pre_request_count. The numbers + * used avoid int16 overflow. + */ + + smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 30000); + status = smb2_getinfo_file(tree, mem_ctx, &qfinfo); + CHECK_STATUS(status, NT_STATUS_OK); + + smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 60000); + status = smb2_getinfo_file(tree, mem_ctx, &qfinfo); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * This final request turns the op->global->channel_sequence + * to the same as we had when sending the notify above. The + * notify's request count has in the meantime moved to + * op->pre_request_count. + */ + + smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 0); + status = smb2_getinfo_file(tree, mem_ctx, &qfinfo); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * At this point op->request_count==0. + * + * The next cancel makes us reply to the notify. Because the + * csn we currently use is the same as we used when sending + * the notify, smbd thinks it must decrement op->request_count + * and not op->pre_request_count. + */ + + status = smb2_cancel(req); + CHECK_STATUS(status, NT_STATUS_OK); + + status = smb2_notify_recv(req, mem_ctx, ¬ify); + CHECK_STATUS(status, NT_STATUS_CANCELLED); + + ret = true; + +done: + if (dh != NULL) { + smb2_util_close(tree, _dh); + } + smb2_deltree(tree, BASEDIR); + talloc_free(tree); + talloc_free(mem_ctx); + + return ret; +} + struct torture_suite *torture_smb2_replay_init(TALLOC_CTX *ctx) { struct torture_suite *suite = @@ -2445,6 +2541,7 @@ struct torture_suite *torture_smb2_replay_init(TALLOC_CTX *ctx) torture_suite_add_1smb2_test(suite, "replay4", test_replay4); torture_suite_add_1smb2_test(suite, "replay5", test_replay5); torture_suite_add_1smb2_test(suite, "replay6", test_replay6); + torture_suite_add_1smb2_test(suite, "replay7", test_replay7); suite->description = talloc_strdup(suite, "SMB2 REPLAY tests"); -- Samba Shared Repository