From: Volker Lendecke Date: Wed, 11 Feb 2026 17:25:30 +0000 (+0100) Subject: rpc_server: Move dfs helper routines to srv_dfs_nt.c X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=ac9f285d971f424dc641c474ee3c744b27a13fb6;p=thirdparty%2Fsamba.git rpc_server: Move dfs helper routines to srv_dfs_nt.c 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 Reviewed-by: Anoop C S --- diff --git a/source3/rpc_server/dfs/srv_dfs_nt.c b/source3/rpc_server/dfs/srv_dfs_nt.c index 262603483eb..8d32f77b9d6 100644 --- a/source3/rpc_server/dfs/srv_dfs_nt.c +++ b/source3/rpc_server/dfs/srv_dfs_nt.c @@ -29,11 +29,511 @@ #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. */ diff --git a/source3/rpc_server/wscript_build b/source3/rpc_server/wscript_build index 2017c9faaa3..4f40d945532 100644 --- a/source3/rpc_server/wscript_build +++ b/source3/rpc_server/wscript_build @@ -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''', diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index e3595b620e8..721faab2cc9 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -62,11 +62,11 @@ 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; -} diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index 2216445767f..e4996a37723 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -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,