]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
rpc_server: Move dfs helper routines to srv_dfs_nt.c
authorVolker Lendecke <vl@samba.org>
Wed, 11 Feb 2026 17:25:30 +0000 (18:25 +0100)
committerVolker Lendecke <vl@samba.org>
Sun, 1 Mar 2026 20:19:35 +0000 (20:19 +0000)
This makes it clear that these callers of create_conn_struct_tos_cwd()
don't really need to chdir() back to whatever cwd the process was in
before. RPC servers don't really have a concept of "implicit" current
working directory that is assumed to be the root dir of the current
share.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Anoop C S <anoopcs@samba.org>
source3/rpc_server/dfs/srv_dfs_nt.c
source3/rpc_server/wscript_build
source3/smbd/msdfs.c
source3/smbd/proto.h

index 262603483ebb85e214638ce7e23a7dae100f2a75..8d32f77b9d6af2223cb339a72a271dacd9b77a65 100644 (file)
 #include "msdfs.h"
 #include "smbd/smbd.h"
 #include "smbd/globals.h"
+#include "smbd/dir.h"
 #include "auth.h"
+#include "source3/lib/global_contexts.h"
+#include "source3/lib/substitute.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_MSDFS
 
+/*********************************************************************
+ Creates a junction structure from a DFS pathname
+**********************************************************************/
+
+static bool create_junction(TALLOC_CTX *ctx,
+                           const char *dfs_path,
+                           struct junction_map *jucn)
+{
+       const struct loadparm_substitution
+               *lp_sub = loadparm_s3_global_substitution();
+       int snum;
+       char *servicename = NULL;
+       char *reqpath = NULL;
+       NTSTATUS status;
+
+       status = parse_dfs_path_strict(
+               ctx, dfs_path, NULL, &servicename, &reqpath);
+       if (!NT_STATUS_IS_OK(status)) {
+               return False;
+       }
+
+       /* Check for a non-DFS share */
+       snum = lp_servicenumber(servicename);
+
+       if (snum < 0 || !lp_msdfs_root(snum)) {
+               DEBUG(4,("create_junction: %s is not an msdfs root.\n",
+                       servicename));
+               return False;
+       }
+
+       /* Junction create paths are always non-POSIX. */
+       status = check_path_syntax(reqpath, false);
+       if (!NT_STATUS_IS_OK(status)) {
+               return false;
+       }
+
+       jucn->service_name = talloc_strdup(ctx, servicename);
+       jucn->volume_name = talloc_strdup(ctx, reqpath);
+       jucn->comment = lp_comment(ctx, lp_sub, snum);
+
+       if (!jucn->service_name || !jucn->volume_name || !jucn->comment) {
+               return False;
+       }
+       return True;
+}
+
+/**********************************************************************
+ Forms a valid Unix pathname from the junction
+ **********************************************************************/
+
+static bool junction_to_local_path_tos(const struct junction_map *jucn,
+                                      struct auth_session_info *session_info,
+                                      char **pp_path_out,
+                                      connection_struct **conn_out)
+{
+       const struct loadparm_substitution
+               *lp_sub = loadparm_s3_global_substitution();
+       struct conn_struct_tos *c = NULL;
+       int snum;
+       char *path_out = NULL;
+       NTSTATUS status;
+
+       snum = lp_servicenumber(jucn->service_name);
+       if (snum < 0) {
+               return False;
+       }
+       status = create_conn_struct_tos_cwd(global_messaging_context(),
+                                           snum,
+                                           lp_path(talloc_tos(),
+                                                   lp_sub,
+                                                   snum),
+                                           session_info,
+                                           &c);
+       if (!NT_STATUS_IS_OK(status)) {
+               return False;
+       }
+
+       path_out = talloc_asprintf(c,
+                                  "%s/%s",
+                                  lp_path(talloc_tos(), lp_sub, snum),
+                                  jucn->volume_name);
+       if (path_out == NULL) {
+               TALLOC_FREE(c);
+               return False;
+       }
+       *pp_path_out = path_out;
+       *conn_out = c->conn;
+       return True;
+}
+
+static bool create_msdfs_link(const struct junction_map *jucn,
+                             struct auth_session_info *session_info)
+{
+       TALLOC_CTX *frame = talloc_stackframe();
+       char *path = NULL;
+       connection_struct *conn;
+       struct smb_filename *smb_fname = NULL;
+       struct smb_filename *parent_fname = NULL;
+       struct smb_filename *at_fname = NULL;
+       bool ok;
+       NTSTATUS status;
+       bool ret = false;
+
+       ok = junction_to_local_path_tos(jucn, session_info, &path, &conn);
+       if (!ok) {
+               goto out;
+       }
+
+       if (!CAN_WRITE(conn)) {
+               const struct loadparm_substitution
+                       *lp_sub = loadparm_s3_global_substitution();
+               int snum = lp_servicenumber(jucn->service_name);
+
+               DBG_WARNING("Can't create DFS entry on read-only share %s\n",
+                           lp_servicename(frame, lp_sub, snum));
+               goto out;
+       }
+
+       smb_fname = cp_smb_basename(frame, path);
+       if (smb_fname == NULL) {
+               goto out;
+       }
+
+       status = parent_pathref(
+               frame, conn->cwd_fsp, smb_fname, &parent_fname, &at_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto out;
+       }
+
+       status = SMB_VFS_CREATE_DFS_PATHAT(conn,
+                                          parent_fname->fsp,
+                                          at_fname,
+                                          jucn->referral_list,
+                                          jucn->referral_count);
+       if (!NT_STATUS_IS_OK(status)) {
+               if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
+                       int retval = SMB_VFS_UNLINKAT(conn,
+                                                     parent_fname->fsp,
+                                                     at_fname,
+                                                     0);
+                       if (retval != 0) {
+                               goto out;
+                       }
+               }
+               status = SMB_VFS_CREATE_DFS_PATHAT(conn,
+                                                  parent_fname->fsp,
+                                                  at_fname,
+                                                  jucn->referral_list,
+                                                  jucn->referral_count);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DBG_WARNING("SMB_VFS_CREATE_DFS_PATHAT failed "
+                                   "%s - Error: %s\n",
+                                   path,
+                                   nt_errstr(status));
+                       goto out;
+               }
+       }
+
+       ret = true;
+
+out:
+       TALLOC_FREE(frame);
+       return ret;
+}
+
+static bool remove_msdfs_link(const struct junction_map *jucn,
+                             struct auth_session_info *session_info)
+{
+       TALLOC_CTX *frame = talloc_stackframe();
+       char *path = NULL;
+       connection_struct *conn;
+       bool ret = False;
+       struct smb_filename *smb_fname;
+       struct smb_filename *parent_fname = NULL;
+       struct smb_filename *at_fname = NULL;
+       NTSTATUS status;
+       bool ok;
+       int retval;
+
+       ok = junction_to_local_path_tos(jucn, session_info, &path, &conn);
+       if (!ok) {
+               TALLOC_FREE(frame);
+               return false;
+       }
+
+       if (!CAN_WRITE(conn)) {
+               const struct loadparm_substitution
+                       *lp_sub = loadparm_s3_global_substitution();
+               int snum = lp_servicenumber(jucn->service_name);
+
+               DBG_WARNING("Can't remove DFS entry on read-only share %s\n",
+                           lp_servicename(frame, lp_sub, snum));
+               TALLOC_FREE(frame);
+               return false;
+       }
+
+       smb_fname = cp_smb_basename(frame, path);
+       if (smb_fname == NULL) {
+               TALLOC_FREE(frame);
+               errno = ENOMEM;
+               return false;
+       }
+
+       status = parent_pathref(
+               frame, conn->cwd_fsp, smb_fname, &parent_fname, &at_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(frame);
+               return false;
+       }
+
+       retval = SMB_VFS_UNLINKAT(conn, parent_fname->fsp, at_fname, 0);
+       if (retval == 0) {
+               ret = True;
+       }
+
+       TALLOC_FREE(frame);
+       return ret;
+}
+
+/*********************************************************************
+ Return the number of DFS links at the root of this share.
+*********************************************************************/
+
+static size_t count_dfs_links(TALLOC_CTX *ctx,
+                             struct auth_session_info *session_info,
+                             int snum)
+{
+       TALLOC_CTX *frame = talloc_stackframe();
+       const struct loadparm_substitution
+               *lp_sub = loadparm_s3_global_substitution();
+       size_t cnt = 0;
+       const char *dname = NULL;
+       char *talloced = NULL;
+       const char *connect_path = lp_path(frame, lp_sub, snum);
+       const char *msdfs_proxy = lp_msdfs_proxy(frame, lp_sub, snum);
+       struct conn_struct_tos *c = NULL;
+       connection_struct *conn = NULL;
+       NTSTATUS status;
+       struct smb_filename *smb_fname = NULL;
+       struct smb_Dir *dir_hnd = NULL;
+
+       if (*connect_path == '\0') {
+               TALLOC_FREE(frame);
+               return 0;
+       }
+
+       /*
+        * Fake up a connection struct for the VFS layer.
+        */
+
+       status = create_conn_struct_tos_cwd(global_messaging_context(),
+                                           snum,
+                                           connect_path,
+                                           session_info,
+                                           &c);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(3, ("create_conn_struct failed: %s\n",
+                         nt_errstr(status)));
+               TALLOC_FREE(frame);
+               return 0;
+       }
+       conn = c->conn;
+
+       /* Count a link for the msdfs root - convention */
+       cnt = 1;
+
+       /* No more links if this is an msdfs proxy. */
+       if (*msdfs_proxy != '\0') {
+               goto out;
+       }
+
+       smb_fname = cp_smb_basename(frame, ".");
+       if (smb_fname == NULL) {
+               goto out;
+       }
+
+       /* Now enumerate all dfs links */
+       status = OpenDir(frame, conn, smb_fname, NULL, 0, &dir_hnd);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
+               goto out;
+       }
+
+       while ((dname = ReadDirName(dir_hnd, &talloced)) != NULL) {
+               struct smb_filename *smb_dname = cp_smb_basename(frame, dname);
+               if (smb_dname == NULL) {
+                       goto out;
+               }
+               if (is_msdfs_link(dir_hnd_fetch_fsp(dir_hnd), smb_dname)) {
+                       if (cnt + 1 < cnt) {
+                               cnt = 0;
+                               goto out;
+                       }
+                       cnt++;
+               }
+               TALLOC_FREE(talloced);
+               TALLOC_FREE(smb_dname);
+       }
+
+out:
+       TALLOC_FREE(frame);
+       return cnt;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+static int form_junctions(TALLOC_CTX *ctx,
+                         struct auth_session_info *session_info,
+                         int snum,
+                         struct junction_map *jucn,
+                         size_t jn_remain)
+{
+       TALLOC_CTX *frame = talloc_stackframe();
+       const struct loadparm_substitution
+               *lp_sub = loadparm_s3_global_substitution();
+       size_t cnt = 0;
+       const char *dname = NULL;
+       char *talloced = NULL;
+       const char *connect_path = lp_path(frame, lp_sub, snum);
+       char *service_name = lp_servicename(frame, lp_sub, snum);
+       const char *msdfs_proxy = lp_msdfs_proxy(frame, lp_sub, snum);
+       struct conn_struct_tos *c = NULL;
+       connection_struct *conn = NULL;
+       struct referral *ref = NULL;
+       struct smb_filename *smb_fname = NULL;
+       struct smb_Dir *dir_hnd = NULL;
+       NTSTATUS status;
+
+       if (jn_remain == 0) {
+               TALLOC_FREE(frame);
+               return 0;
+       }
+
+       if (*connect_path == '\0') {
+               TALLOC_FREE(frame);
+               return 0;
+       }
+
+       /*
+        * Fake up a connection struct for the VFS layer.
+        */
+
+       status = create_conn_struct_tos_cwd(global_messaging_context(),
+                                           snum,
+                                           connect_path,
+                                           session_info,
+                                           &c);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(3, ("create_conn_struct failed: %s\n",
+                         nt_errstr(status)));
+               TALLOC_FREE(frame);
+               return 0;
+       }
+       conn = c->conn;
+
+       /* form a junction for the msdfs root - convention
+          DO NOT REMOVE THIS: NT clients will not work with us
+          if this is not present
+       */
+       jucn[cnt].service_name = talloc_strdup(ctx, service_name);
+       jucn[cnt].volume_name = talloc_strdup(ctx, "");
+       if (!jucn[cnt].service_name || !jucn[cnt].volume_name) {
+               goto out;
+       }
+       jucn[cnt].comment = "";
+       jucn[cnt].referral_count = 1;
+
+       ref = jucn[cnt].referral_list = talloc_zero(ctx, struct referral);
+       if (jucn[cnt].referral_list == NULL) {
+               goto out;
+       }
+
+       ref->proximity = 0;
+       ref->ttl = REFERRAL_TTL;
+       if (*msdfs_proxy != '\0') {
+               ref->alternate_path = talloc_strdup(ctx, msdfs_proxy);
+       } else {
+               ref->alternate_path = talloc_asprintf(ctx,
+                                                     "\\\\%s\\%s",
+                                                     get_local_machine_name(),
+                                                     service_name);
+       }
+
+       if (!ref->alternate_path) {
+               goto out;
+       }
+       cnt++;
+
+       /* Don't enumerate if we're an msdfs proxy. */
+       if (*msdfs_proxy != '\0') {
+               goto out;
+       }
+
+       smb_fname = cp_smb_basename(frame, ".");
+       if (smb_fname == NULL) {
+               goto out;
+       }
+
+       /* Now enumerate all dfs links */
+       status = OpenDir(frame, conn, smb_fname, NULL, 0, &dir_hnd);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
+               goto out;
+       }
+
+       while ((dname = ReadDirName(dir_hnd, &talloced)) != NULL) {
+               struct smb_filename *smb_dname = NULL;
+
+               if (cnt >= jn_remain) {
+                       DEBUG(2, ("form_junctions: ran out of MSDFS "
+                               "junction slots\n"));
+                       TALLOC_FREE(talloced);
+                       goto out;
+               }
+               smb_dname = cp_smb_basename(talloc_tos(), dname);
+               if (smb_dname == NULL) {
+                       TALLOC_FREE(talloced);
+                       goto out;
+               }
+
+               status = SMB_VFS_READ_DFS_PATHAT(conn,
+                                                ctx,
+                                                conn->cwd_fsp,
+                                                smb_dname,
+                                                &jucn[cnt].referral_list,
+                                                &jucn[cnt].referral_count);
+
+               if (NT_STATUS_IS_OK(status)) {
+                       jucn[cnt].service_name = talloc_strdup(ctx,
+                                                              service_name);
+                       jucn[cnt].volume_name = talloc_strdup(ctx, dname);
+                       if (!jucn[cnt].service_name || !jucn[cnt].volume_name)
+                       {
+                               TALLOC_FREE(talloced);
+                               goto out;
+                       }
+                       jucn[cnt].comment = "";
+                       cnt++;
+               }
+               TALLOC_FREE(talloced);
+               TALLOC_FREE(smb_dname);
+       }
+
+out:
+       TALLOC_FREE(frame);
+       return cnt;
+}
+
+static struct junction_map *enum_msdfs_links(
+       TALLOC_CTX *ctx,
+       struct auth_session_info *session_info,
+       size_t *p_num_jn)
+{
+       struct junction_map *jn = NULL;
+       int i = 0;
+       size_t jn_count = 0;
+       int sharecount = 0;
+
+       *p_num_jn = 0;
+       if (!lp_host_msdfs()) {
+               return NULL;
+       }
+
+       /* Ensure all the usershares are loaded. */
+       become_root();
+       load_registry_shares();
+       sharecount = load_usershare_shares(NULL, connections_snum_used);
+       unbecome_root();
+
+       for (i = 0; i < sharecount; i++) {
+               if (lp_msdfs_root(i)) {
+                       jn_count += count_dfs_links(ctx, session_info, i);
+               }
+       }
+       if (jn_count == 0) {
+               return NULL;
+       }
+       jn = talloc_array(ctx, struct junction_map, jn_count);
+       if (!jn) {
+               return NULL;
+       }
+       for (i = 0; i < sharecount; i++) {
+               if (*p_num_jn >= jn_count) {
+                       break;
+               }
+               if (lp_msdfs_root(i)) {
+                       *p_num_jn += form_junctions(ctx,
+                                                   session_info,
+                                                   i,
+                                                   &jn[*p_num_jn],
+                                                   jn_count - *p_num_jn);
+               }
+       }
+       return jn;
+}
+
 /* This function does not return a WERROR or NTSTATUS code but rather 1 if
    dfs exists, or 0 otherwise. */
 
index 2017c9faaa378aafe7cb4ef1603519b98aa212b3..4f40d945532e35da5cb26ef3cf142b6122e4aa04 100644 (file)
@@ -181,7 +181,7 @@ bld.SAMBA3_SUBSYSTEM('RPC_LSARPC',
 
 bld.SAMBA3_SUBSYSTEM('RPC_NETDFS',
                     source='''dfs/srv_dfs_nt.c''',
-                    deps='samba-util')
+                    deps='samba-util smbd_base RPC_SERVER_LOOP')
 
 bld.SAMBA3_SUBSYSTEM('RPC_NETLOGON',
                      source='''netlogon/srv_netlog_nt.c''',
index e3595b620e8d12e5fc1ca992343346e5e756973b..721faab2cc91b4c8b336420eeb03dd993bc2aed5 100644 (file)
  etc. Errors out on any inconsistency in the path.
 **********************************************************************/
 
-static NTSTATUS parse_dfs_path_strict(TALLOC_CTX *ctx,
-                               const char *pathname,
-                               char **_hostname,
-                               char **_servicename,
-                               char **_remaining_path)
+NTSTATUS parse_dfs_path_strict(TALLOC_CTX *ctx,
+                              const char *pathname,
+                              char **_hostname,
+                              char **_servicename,
+                              char **_remaining_path)
 {
        char *pathname_local = NULL;
        char *p = NULL;
@@ -1148,102 +1148,6 @@ int setup_dfs_referral(connection_struct *orig_conn,
        return reply_size;
 }
 
-/**********************************************************************
- The following functions are called by the NETDFS RPC pipe functions
- **********************************************************************/
-
-/*********************************************************************
- Creates a junction structure from a DFS pathname
-**********************************************************************/
-
-bool create_junction(TALLOC_CTX *ctx,
-               const char *dfs_path,
-               struct junction_map *jucn)
-{
-       const struct loadparm_substitution *lp_sub =
-               loadparm_s3_global_substitution();
-       int snum;
-       char *servicename = NULL;
-       char *reqpath = NULL;
-       NTSTATUS status;
-
-       status = parse_dfs_path_strict(
-                               ctx,
-                               dfs_path,
-                               NULL,
-                               &servicename,
-                               &reqpath);
-       if (!NT_STATUS_IS_OK(status)) {
-               return False;
-       }
-
-       /* Check for a non-DFS share */
-       snum = lp_servicenumber(servicename);
-
-       if(snum < 0 || !lp_msdfs_root(snum)) {
-               DEBUG(4,("create_junction: %s is not an msdfs root.\n",
-                       servicename));
-               return False;
-       }
-
-       /* Junction create paths are always non-POSIX. */
-       status = check_path_syntax(reqpath, false);
-       if (!NT_STATUS_IS_OK(status)) {
-               return false;
-       }
-
-       jucn->service_name = talloc_strdup(ctx, servicename);
-       jucn->volume_name = talloc_strdup(ctx, reqpath);
-       jucn->comment = lp_comment(ctx, lp_sub, snum);
-
-       if (!jucn->service_name || !jucn->volume_name || ! jucn->comment) {
-               return False;
-       }
-       return True;
-}
-
-/**********************************************************************
- Forms a valid Unix pathname from the junction
- **********************************************************************/
-
-static bool junction_to_local_path_tos(const struct junction_map *jucn,
-                                      struct auth_session_info *session_info,
-                                      char **pp_path_out,
-                                      connection_struct **conn_out)
-{
-       const struct loadparm_substitution *lp_sub =
-               loadparm_s3_global_substitution();
-       struct conn_struct_tos *c = NULL;
-       int snum;
-       char *path_out = NULL;
-       NTSTATUS status;
-
-       snum = lp_servicenumber(jucn->service_name);
-       if(snum < 0) {
-               return False;
-       }
-       status = create_conn_struct_tos_cwd(global_messaging_context(),
-                                           snum,
-                                           lp_path(talloc_tos(), lp_sub, snum),
-                                           session_info,
-                                           &c);
-       if (!NT_STATUS_IS_OK(status)) {
-               return False;
-       }
-
-       path_out = talloc_asprintf(c,
-                       "%s/%s",
-                       lp_path(talloc_tos(), lp_sub, snum),
-                       jucn->volume_name);
-       if (path_out == NULL) {
-               TALLOC_FREE(c);
-               return False;
-       }
-       *pp_path_out = path_out;
-       *conn_out = c->conn;
-       return True;
-}
-
 /*
  * Create a msdfs string in Samba format we can store
  * in a filesystem object (currently a symlink).
@@ -1306,428 +1210,3 @@ char *msdfs_link_string(TALLOC_CTX *ctx,
        TALLOC_FREE(msdfs_link);
        return NULL;
 }
-
-bool create_msdfs_link(const struct junction_map *jucn,
-                      struct auth_session_info *session_info)
-{
-       TALLOC_CTX *frame = talloc_stackframe();
-       char *path = NULL;
-       connection_struct *conn;
-       struct smb_filename *smb_fname = NULL;
-       struct smb_filename *parent_fname = NULL;
-       struct smb_filename *at_fname = NULL;
-       bool ok;
-       NTSTATUS status;
-       bool ret = false;
-
-       ok = junction_to_local_path_tos(jucn, session_info, &path, &conn);
-       if (!ok) {
-               goto out;
-       }
-
-       if (!CAN_WRITE(conn)) {
-               const struct loadparm_substitution *lp_sub =
-                       loadparm_s3_global_substitution();
-               int snum = lp_servicenumber(jucn->service_name);
-
-               DBG_WARNING("Can't create DFS entry on read-only share %s\n",
-                       lp_servicename(frame, lp_sub, snum));
-               goto out;
-       }
-
-       smb_fname = cp_smb_basename(frame, path);
-       if (smb_fname == NULL) {
-               goto out;
-       }
-
-       status = parent_pathref(frame,
-                               conn->cwd_fsp,
-                               smb_fname,
-                               &parent_fname,
-                               &at_fname);
-       if (!NT_STATUS_IS_OK(status)) {
-               goto out;
-       }
-
-       status = SMB_VFS_CREATE_DFS_PATHAT(conn,
-                               parent_fname->fsp,
-                               at_fname,
-                               jucn->referral_list,
-                               jucn->referral_count);
-       if (!NT_STATUS_IS_OK(status)) {
-               if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
-                       int retval = SMB_VFS_UNLINKAT(conn,
-                                               parent_fname->fsp,
-                                               at_fname,
-                                               0);
-                       if (retval != 0) {
-                               goto out;
-                       }
-               }
-               status = SMB_VFS_CREATE_DFS_PATHAT(conn,
-                               parent_fname->fsp,
-                               at_fname,
-                               jucn->referral_list,
-                               jucn->referral_count);
-               if (!NT_STATUS_IS_OK(status)) {
-                       DBG_WARNING("SMB_VFS_CREATE_DFS_PATHAT failed "
-                               "%s - Error: %s\n",
-                               path,
-                               nt_errstr(status));
-                       goto out;
-               }
-       }
-
-       ret = true;
-
-out:
-       TALLOC_FREE(frame);
-       return ret;
-}
-
-bool remove_msdfs_link(const struct junction_map *jucn,
-                      struct auth_session_info *session_info)
-{
-       TALLOC_CTX *frame = talloc_stackframe();
-       char *path = NULL;
-       connection_struct *conn;
-       bool ret = False;
-       struct smb_filename *smb_fname;
-       struct smb_filename *parent_fname = NULL;
-       struct smb_filename *at_fname = NULL;
-       NTSTATUS status;
-       bool ok;
-       int retval;
-
-       ok = junction_to_local_path_tos(jucn, session_info, &path, &conn);
-       if (!ok) {
-               TALLOC_FREE(frame);
-               return false;
-       }
-
-       if (!CAN_WRITE(conn)) {
-               const struct loadparm_substitution *lp_sub =
-                       loadparm_s3_global_substitution();
-               int snum = lp_servicenumber(jucn->service_name);
-
-               DBG_WARNING("Can't remove DFS entry on read-only share %s\n",
-                       lp_servicename(frame, lp_sub, snum));
-               TALLOC_FREE(frame);
-               return false;
-       }
-
-       smb_fname = cp_smb_basename(frame, path);
-       if (smb_fname == NULL) {
-               TALLOC_FREE(frame);
-               errno = ENOMEM;
-               return false;
-       }
-
-       status = parent_pathref(frame,
-                               conn->cwd_fsp,
-                               smb_fname,
-                               &parent_fname,
-                               &at_fname);
-       if (!NT_STATUS_IS_OK(status)) {
-               TALLOC_FREE(frame);
-               return false;
-       }
-
-       retval = SMB_VFS_UNLINKAT(conn,
-                       parent_fname->fsp,
-                       at_fname,
-                       0);
-       if (retval == 0) {
-               ret = True;
-       }
-
-       TALLOC_FREE(frame);
-       return ret;
-}
-
-/*********************************************************************
- Return the number of DFS links at the root of this share.
-*********************************************************************/
-
-static size_t count_dfs_links(TALLOC_CTX *ctx,
-                             struct auth_session_info *session_info,
-                             int snum)
-{
-       TALLOC_CTX *frame = talloc_stackframe();
-       const struct loadparm_substitution *lp_sub =
-               loadparm_s3_global_substitution();
-       size_t cnt = 0;
-       const char *dname = NULL;
-       char *talloced = NULL;
-       const char *connect_path = lp_path(frame, lp_sub, snum);
-       const char *msdfs_proxy = lp_msdfs_proxy(frame, lp_sub, snum);
-       struct conn_struct_tos *c = NULL;
-       connection_struct *conn = NULL;
-       NTSTATUS status;
-       struct smb_filename *smb_fname = NULL;
-       struct smb_Dir *dir_hnd = NULL;
-
-       if(*connect_path == '\0') {
-               TALLOC_FREE(frame);
-               return 0;
-       }
-
-       /*
-        * Fake up a connection struct for the VFS layer.
-        */
-
-       status = create_conn_struct_tos_cwd(global_messaging_context(),
-                                           snum,
-                                           connect_path,
-                                           session_info,
-                                           &c);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(3, ("create_conn_struct failed: %s\n",
-                         nt_errstr(status)));
-               TALLOC_FREE(frame);
-               return 0;
-       }
-       conn = c->conn;
-
-       /* Count a link for the msdfs root - convention */
-       cnt = 1;
-
-       /* No more links if this is an msdfs proxy. */
-       if (*msdfs_proxy != '\0') {
-               goto out;
-       }
-
-       smb_fname = cp_smb_basename(frame, ".");
-       if (smb_fname == NULL) {
-               goto out;
-       }
-
-       /* Now enumerate all dfs links */
-       status = OpenDir(frame,
-                        conn,
-                        smb_fname,
-                        NULL,
-                        0,
-                        &dir_hnd);
-       if (!NT_STATUS_IS_OK(status)) {
-               errno = map_errno_from_nt_status(status);
-               goto out;
-       }
-
-       while ((dname = ReadDirName(dir_hnd, &talloced)) != NULL) {
-               struct smb_filename *smb_dname = cp_smb_basename(frame, dname);
-               if (smb_dname == NULL) {
-                       goto out;
-               }
-               if (is_msdfs_link(dir_hnd_fetch_fsp(dir_hnd), smb_dname)) {
-                       if (cnt + 1 < cnt) {
-                               cnt = 0;
-                               goto out;
-                       }
-                       cnt++;
-               }
-               TALLOC_FREE(talloced);
-               TALLOC_FREE(smb_dname);
-       }
-
-out:
-       TALLOC_FREE(frame);
-       return cnt;
-}
-
-/*********************************************************************
-*********************************************************************/
-
-static int form_junctions(TALLOC_CTX *ctx,
-                         struct auth_session_info *session_info,
-                               int snum,
-                               struct junction_map *jucn,
-                               size_t jn_remain)
-{
-       TALLOC_CTX *frame = talloc_stackframe();
-       const struct loadparm_substitution *lp_sub =
-               loadparm_s3_global_substitution();
-       size_t cnt = 0;
-       const char *dname = NULL;
-       char *talloced = NULL;
-       const char *connect_path = lp_path(frame, lp_sub, snum);
-       char *service_name = lp_servicename(frame, lp_sub, snum);
-       const char *msdfs_proxy = lp_msdfs_proxy(frame, lp_sub, snum);
-       struct conn_struct_tos *c = NULL;
-       connection_struct *conn = NULL;
-       struct referral *ref = NULL;
-       struct smb_filename *smb_fname = NULL;
-       struct smb_Dir *dir_hnd = NULL;
-       NTSTATUS status;
-
-       if (jn_remain == 0) {
-               TALLOC_FREE(frame);
-               return 0;
-       }
-
-       if(*connect_path == '\0') {
-               TALLOC_FREE(frame);
-               return 0;
-       }
-
-       /*
-        * Fake up a connection struct for the VFS layer.
-        */
-
-       status = create_conn_struct_tos_cwd(global_messaging_context(),
-                                           snum,
-                                           connect_path,
-                                           session_info,
-                                           &c);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(3, ("create_conn_struct failed: %s\n",
-                         nt_errstr(status)));
-               TALLOC_FREE(frame);
-               return 0;
-       }
-       conn = c->conn;
-
-       /* form a junction for the msdfs root - convention
-          DO NOT REMOVE THIS: NT clients will not work with us
-          if this is not present
-       */
-       jucn[cnt].service_name = talloc_strdup(ctx,service_name);
-       jucn[cnt].volume_name = talloc_strdup(ctx, "");
-       if (!jucn[cnt].service_name || !jucn[cnt].volume_name) {
-               goto out;
-       }
-       jucn[cnt].comment = "";
-       jucn[cnt].referral_count = 1;
-
-       ref = jucn[cnt].referral_list = talloc_zero(ctx, struct referral);
-       if (jucn[cnt].referral_list == NULL) {
-               goto out;
-       }
-
-       ref->proximity = 0;
-       ref->ttl = REFERRAL_TTL;
-       if (*msdfs_proxy != '\0') {
-               ref->alternate_path = talloc_strdup(ctx,
-                                               msdfs_proxy);
-       } else {
-               ref->alternate_path = talloc_asprintf(ctx,
-                       "\\\\%s\\%s",
-                       get_local_machine_name(),
-                       service_name);
-       }
-
-       if (!ref->alternate_path) {
-               goto out;
-       }
-       cnt++;
-
-       /* Don't enumerate if we're an msdfs proxy. */
-       if (*msdfs_proxy != '\0') {
-               goto out;
-       }
-
-       smb_fname = cp_smb_basename(frame, ".");
-       if (smb_fname == NULL) {
-               goto out;
-       }
-
-       /* Now enumerate all dfs links */
-       status = OpenDir(frame,
-                        conn,
-                        smb_fname,
-                        NULL,
-                        0,
-                        &dir_hnd);
-       if (!NT_STATUS_IS_OK(status)) {
-               errno = map_errno_from_nt_status(status);
-               goto out;
-       }
-
-       while ((dname = ReadDirName(dir_hnd, &talloced)) != NULL) {
-               struct smb_filename *smb_dname = NULL;
-
-               if (cnt >= jn_remain) {
-                       DEBUG(2, ("form_junctions: ran out of MSDFS "
-                               "junction slots\n"));
-                       TALLOC_FREE(talloced);
-                       goto out;
-               }
-               smb_dname = cp_smb_basename(talloc_tos(), dname);
-               if (smb_dname == NULL) {
-                       TALLOC_FREE(talloced);
-                       goto out;
-               }
-
-               status = SMB_VFS_READ_DFS_PATHAT(conn,
-                               ctx,
-                               conn->cwd_fsp,
-                               smb_dname,
-                               &jucn[cnt].referral_list,
-                               &jucn[cnt].referral_count);
-
-               if (NT_STATUS_IS_OK(status)) {
-                       jucn[cnt].service_name = talloc_strdup(ctx,
-                                                       service_name);
-                       jucn[cnt].volume_name = talloc_strdup(ctx, dname);
-                       if (!jucn[cnt].service_name || !jucn[cnt].volume_name) {
-                               TALLOC_FREE(talloced);
-                               goto out;
-                       }
-                       jucn[cnt].comment = "";
-                       cnt++;
-               }
-               TALLOC_FREE(talloced);
-               TALLOC_FREE(smb_dname);
-       }
-
-out:
-       TALLOC_FREE(frame);
-       return cnt;
-}
-
-struct junction_map *enum_msdfs_links(TALLOC_CTX *ctx,
-                                     struct auth_session_info *session_info,
-                                     size_t *p_num_jn)
-{
-       struct junction_map *jn = NULL;
-       int i=0;
-       size_t jn_count = 0;
-       int sharecount = 0;
-
-       *p_num_jn = 0;
-       if(!lp_host_msdfs()) {
-               return NULL;
-       }
-
-       /* Ensure all the usershares are loaded. */
-       become_root();
-       load_registry_shares();
-       sharecount = load_usershare_shares(NULL, connections_snum_used);
-       unbecome_root();
-
-       for(i=0;i < sharecount;i++) {
-               if(lp_msdfs_root(i)) {
-                       jn_count += count_dfs_links(ctx, session_info, i);
-               }
-       }
-       if (jn_count == 0) {
-               return NULL;
-       }
-       jn = talloc_array(ctx,  struct junction_map, jn_count);
-       if (!jn) {
-               return NULL;
-       }
-       for(i=0; i < sharecount; i++) {
-               if (*p_num_jn >= jn_count) {
-                       break;
-               }
-               if(lp_msdfs_root(i)) {
-                       *p_num_jn += form_junctions(ctx,
-                                       session_info,
-                                       i,
-                                       &jn[*p_num_jn],
-                                       jn_count - *p_num_jn);
-               }
-       }
-       return jn;
-}
index 2216445767f1a798cf0cc698d8af630c888c5f35..e4996a377230e382387e733d66e4289b45b6a0fd 100644 (file)
@@ -490,24 +490,21 @@ int setup_dfs_referral(connection_struct *orig_conn,
                        const char *dfs_path,
                        int max_referral_level,
                        char **ppdata, NTSTATUS *pstatus);
-bool create_junction(TALLOC_CTX *ctx,
-               const char *dfs_path,
-               struct junction_map *jucn);
+
 struct referral;
 char *msdfs_link_string(TALLOC_CTX *ctx,
                const struct referral *reflist,
                size_t referral_count);
-bool create_msdfs_link(const struct junction_map *jucn,
-                      struct auth_session_info *session_info);
-bool remove_msdfs_link(const struct junction_map *jucn,
-                      struct auth_session_info *session_info);
-
-struct junction_map *enum_msdfs_links(TALLOC_CTX *ctx,
-                                     struct auth_session_info *session_info,
-                                     size_t *p_num_jn);
+
 struct connection_struct;
 struct smb_filename;
 
+NTSTATUS parse_dfs_path_strict(TALLOC_CTX *ctx,
+                              const char *pathname,
+                              char **_hostname,
+                              char **_servicename,
+                              char **_remaining_path);
+
 NTSTATUS create_conn_struct_cwd(TALLOC_CTX *mem_ctx,
                                struct tevent_context *ev,
                                struct messaging_context *msg,