#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. */
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''',
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;
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).
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;
-}
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,