From cab91684e51356215a4c764e1673e4fd8420b8e8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 3 Apr 2007 22:59:55 +0000 Subject: r22064: Fix the DFS code to work better with Vista clients. Allow "host msdfs = true" to be set in the [global] section and allow Vista to see shares with "msdfs root = yes" and "msdfs root = no" off the same server. Down to an error message really :-). Jeremy. (This used to be commit 1a0f69bb21fd03a18514dfc93c84568708144e28) --- source3/rpc_server/srv_dfs_nt.c | 6 ++-- source3/smbd/msdfs.c | 68 ++++++++++++++++++++++------------------- source3/smbd/trans2.c | 5 +-- 3 files changed, 42 insertions(+), 37 deletions(-) diff --git a/source3/rpc_server/srv_dfs_nt.c b/source3/rpc_server/srv_dfs_nt.c index c7adffd62f..56c1ce00ab 100644 --- a/source3/rpc_server/srv_dfs_nt.c +++ b/source3/rpc_server/srv_dfs_nt.c @@ -61,7 +61,7 @@ WERROR _dfs_Add(pipes_struct *p, struct dfs_Add *r) pstrcat(altpath, r->in.share); /* The following call can change the cwd. */ - if(get_referred_path(p->mem_ctx, r->in.path, &jn, &consumedcnt, &self_ref)) { + if(NT_STATUS_IS_OK(get_referred_path(p->mem_ctx, r->in.path, &jn, &consumedcnt, &self_ref))) { exists = True; jn.referral_count += 1; old_referral_list = jn.referral_list; @@ -119,7 +119,7 @@ WERROR _dfs_Remove(pipes_struct *p, struct dfs_Remove *r) DEBUG(5,("init_reply_dfs_remove: Request to remove %s -> %s\\%s.\n", r->in.path, r->in.server, r->in.share)); - if(!get_referred_path(p->mem_ctx, r->in.path, &jn, &consumedcnt, &self_ref)) { + if(!NT_STATUS_IS_OK(get_referred_path(p->mem_ctx, r->in.path, &jn, &consumedcnt, &self_ref))) { return WERR_DFS_NO_SUCH_VOL; } @@ -313,7 +313,7 @@ WERROR _dfs_GetInfo(pipes_struct *p, struct dfs_GetInfo *r) return WERR_DFS_NO_SUCH_SERVER; /* The following call can change the cwd. */ - if(!get_referred_path(p->mem_ctx, r->in.path, &jn, &consumedcnt, &self_ref) || consumedcnt < strlen(r->in.path)) { + if(!NT_STATUS_IS_OK(get_referred_path(p->mem_ctx, r->in.path, &jn, &consumedcnt, &self_ref)) || consumedcnt < strlen(r->in.path)) { vfs_ChDir(p->conn,p->conn->connectpath); return WERR_DFS_NO_SUCH_VOL; } diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 397d43b8bb..effe868657 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -170,7 +170,7 @@ static NTSTATUS parse_dfs_path(const char *pathname, Note this CHANGES CWD !!!! JRA. *********************************************************/ -static BOOL create_conn_struct(connection_struct *conn, int snum, const char *path) +static NTSTATUS create_conn_struct(connection_struct *conn, int snum, const char *path) { pstring connpath; @@ -183,12 +183,12 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, const char *pa if ((conn->mem_ctx=talloc_init("connection_struct")) == NULL) { DEBUG(0,("talloc_init(connection_struct) failed!\n")); - return False; + return NT_STATUS_NO_MEMORY; } if (!(conn->params = TALLOC_ZERO_P(conn->mem_ctx, struct share_params))) { DEBUG(0, ("TALLOC failed\n")); - return False; + return NT_STATUS_NO_MEMORY; } conn->params->service = snum; @@ -196,9 +196,10 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, const char *pa set_conn_connectpath(conn, connpath); if (!smbd_vfs_init(conn)) { + NTSTATUS status = map_nt_error_from_unix(errno); DEBUG(0,("create_conn_struct: smbd_vfs_init failed.\n")); conn_free_internal(conn); - return False; + return status; } /* @@ -208,13 +209,14 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, const char *pa */ if (vfs_ChDir(conn,conn->connectpath) != 0) { + NTSTATUS status = map_nt_error_from_unix(errno); DEBUG(3,("create_conn_struct: Can't ChDir to new conn path %s. Error was %s\n", conn->connectpath, strerror(errno) )); conn_free_internal(conn); - return False; + return status; } - return True; + return NT_STATUS_OK; } /********************************************************************** @@ -542,7 +544,7 @@ static NTSTATUS dfs_redirect( connection_struct *conn, Return a self referral. **********************************************************************/ -static BOOL self_ref(TALLOC_CTX *ctx, +static NTSTATUS self_ref(TALLOC_CTX *ctx, const char *dfs_path, struct junction_map *jucn, int *consumedcntp, @@ -555,7 +557,7 @@ static BOOL self_ref(TALLOC_CTX *ctx, jucn->referral_count = 1; if((ref = TALLOC_ZERO_P(ctx, struct referral)) == NULL) { DEBUG(0,("self_ref: talloc failed for referral\n")); - return False; + return NT_STATUS_NO_MEMORY; } pstrcpy(ref->alternate_path,dfs_path); @@ -563,7 +565,7 @@ static BOOL self_ref(TALLOC_CTX *ctx, ref->ttl = REFERRAL_TTL; jucn->referral_list = ref; *consumedcntp = strlen(dfs_path); - return True; + return NT_STATUS_OK; } /********************************************************************** @@ -571,7 +573,7 @@ static BOOL self_ref(TALLOC_CTX *ctx, junction_map structure. **********************************************************************/ -BOOL get_referred_path(TALLOC_CTX *ctx, +NTSTATUS get_referred_path(TALLOC_CTX *ctx, const char *dfs_path, struct junction_map *jucn, int *consumedcntp, @@ -583,8 +585,7 @@ BOOL get_referred_path(TALLOC_CTX *ctx, pstring conn_path; pstring targetpath; int snum; - NTSTATUS status; - BOOL ret = False; + NTSTATUS status = NT_STATUS_NOT_FOUND; BOOL dummy; ZERO_STRUCT(conns); @@ -593,14 +594,14 @@ BOOL get_referred_path(TALLOC_CTX *ctx, status = parse_dfs_path(dfs_path, False, &dp, &dummy); if (!NT_STATUS_IS_OK(status)) { - return False; + return status; } /* Verify hostname in path */ if (!is_myname_or_ipaddr(dp.hostname)) { DEBUG(3, ("get_referred_path: Invalid hostname %s in path %s\n", dp.hostname, dfs_path)); - return False; + return NT_STATUS_NOT_FOUND; } fstrcpy(jucn->service_name, dp.servicename); @@ -610,14 +611,14 @@ BOOL get_referred_path(TALLOC_CTX *ctx, snum = lp_servicenumber(jucn->service_name); if(snum < 0) { if ((snum = find_service(jucn->service_name)) < 0) { - return False; + return NT_STATUS_NOT_FOUND; } } if (!lp_msdfs_root(snum)) { DEBUG(3,("get_referred_path: |%s| in dfs path %s is not a dfs root.\n", dp.servicename, dfs_path)); - goto out; + return NT_STATUS_NOT_FOUND; } /* @@ -646,7 +647,7 @@ BOOL get_referred_path(TALLOC_CTX *ctx, jucn->referral_count = 1; if ((ref = TALLOC_ZERO_P(ctx, struct referral)) == NULL) { DEBUG(0, ("malloc failed for referral\n")); - goto out; + return NT_STATUS_NO_MEMORY; } pstrcpy(ref->alternate_path, lp_msdfs_proxy(snum)); @@ -657,13 +658,13 @@ BOOL get_referred_path(TALLOC_CTX *ctx, ref->ttl = REFERRAL_TTL; jucn->referral_list = ref; *consumedcntp = strlen(dfs_path); - ret = True; - goto out; + return NT_STATUS_OK; } pstrcpy(conn_path, lp_pathname(snum)); - if (!create_conn_struct(conn, snum, conn_path)) { - return False; + status = create_conn_struct(conn, snum, conn_path); + if (!NT_STATUS_IS_OK(status)) { + return status; } /* If this is a DFS path dfs_lookup should return @@ -675,7 +676,8 @@ BOOL get_referred_path(TALLOC_CTX *ctx, if (!NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) { DEBUG(3,("get_referred_path: No valid referrals for path %s\n", dfs_path)); - goto out; + conn_free_internal(conn); + return status; } /* We know this is a valid dfs link. Parse the targetpath. */ @@ -684,15 +686,12 @@ BOOL get_referred_path(TALLOC_CTX *ctx, &jucn->referral_count)) { DEBUG(3,("get_referred_path: failed to parse symlink " "target %s\n", targetpath )); - goto out; + conn_free_internal(conn); + return NT_STATUS_NOT_FOUND; } - ret = True; - -out: - conn_free_internal(conn); - return ret; + return NT_STATUS_OK; } static int setup_ver2_dfs_referral(const char *pathname, @@ -890,7 +889,7 @@ static int setup_ver3_dfs_referral(const char *pathname, int setup_dfs_referral(connection_struct *orig_conn, const char *dfs_path, int max_referral_level, - char **ppdata) + char **ppdata, NTSTATUS *pstatus) { struct junction_map junction; int consumedcnt = 0; @@ -901,6 +900,7 @@ int setup_dfs_referral(connection_struct *orig_conn, TALLOC_CTX *ctx; if (!(ctx=talloc_init("setup_dfs_referral"))) { + *pstatus = NT_STATUS_NO_MEMORY; return -1; } @@ -909,6 +909,7 @@ int setup_dfs_referral(connection_struct *orig_conn, /* get the junction entry */ if (!dfs_path) { talloc_destroy(ctx); + *pstatus = NT_STATUS_NOT_FOUND; return -1; } @@ -924,7 +925,8 @@ int setup_dfs_referral(connection_struct *orig_conn, } /* The following call can change cwd. */ - if (!get_referred_path(ctx, pathnamep, &junction, &consumedcnt, &self_referral)) { + *pstatus = get_referred_path(ctx, pathnamep, &junction, &consumedcnt, &self_referral); + if (!NT_STATUS_IS_OK(*pstatus)) { vfs_ChDir(orig_conn,orig_conn->connectpath); talloc_destroy(ctx); return -1; @@ -965,6 +967,7 @@ int setup_dfs_referral(connection_struct *orig_conn, default: DEBUG(0,("setup_dfs_referral: Invalid dfs referral version: %d\n", max_referral_level)); talloc_destroy(ctx); + *pstatus = NT_STATUS_INVALID_LEVEL; return -1; } @@ -974,6 +977,7 @@ int setup_dfs_referral(connection_struct *orig_conn, } talloc_destroy(ctx); + *pstatus = NT_STATUS_OK; return reply_size; } @@ -1041,7 +1045,7 @@ static BOOL junction_to_local_path(struct junction_map *jucn, safe_strcat(path, jucn->volume_name, max_pathlen-1); pstrcpy(conn_path, lp_pathname(snum)); - if (!create_conn_struct(conn_out, snum, conn_path)) { + if (!NT_STATUS_IS_OK(create_conn_struct(conn_out, snum, conn_path))) { return False; } @@ -1160,7 +1164,7 @@ static int form_junctions(TALLOC_CTX *ctx, * Fake up a connection struct for the VFS layer. */ - if (!create_conn_struct(&conn, snum, connect_path)) { + if (!NT_STATUS_IS_OK(create_conn_struct(&conn, snum, connect_path))) { return 0; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index dfba188b74..04969784c0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -6214,6 +6214,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* pstring pathname; int reply_size = 0; int max_referral_level; + NTSTATUS status = NT_STATUS_OK; DEBUG(10,("call_trans2getdfsreferral\n")); @@ -6227,8 +6228,8 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* return ERROR_DOS(ERRDOS,ERRbadfunc); srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), total_params - 2, STR_TERMINATE); - if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0) - return UNIXERROR(ERRDOS,ERRbadfile); + if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0) + return ERROR_NT(status); SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES); send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes); -- cgit