1
0
mirror of https://github.com/samba-team/samba.git synced 2025-06-21 03:17:08 +03:00

Fix bug 6572 - libsmbclient: unable to access 'msdfs proxy' share.

This commit is contained in:
SATOH Fumiyasu 2009-10-28 12:48:36 -07:00 committed by Jeremy Allison
parent 0ba004dc7d
commit c27194a7e0
3 changed files with 121 additions and 47 deletions

View File

@ -2258,6 +2258,15 @@ bool cli_resolve_path(TALLOC_CTX *ctx,
struct cli_state **targetcli, struct cli_state **targetcli,
char **pp_targetpath); char **pp_targetpath);
bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
struct cli_state *cli,
const char *sharename,
char **pp_newserver,
char **pp_newshare,
bool force_encrypt,
const char *username,
const char *password,
const char *domain);
/* The following definitions come from libsmb/clidgram.c */ /* The following definitions come from libsmb/clidgram.c */
bool send_getdc_request(TALLOC_CTX *mem_ctx, bool send_getdc_request(TALLOC_CTX *mem_ctx,

View File

@ -32,16 +32,6 @@
as a separator when looking at the pathname part.... JRA. as a separator when looking at the pathname part.... JRA.
********************************************************************/ ********************************************************************/
static bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
struct cli_state *cli,
const char *sharename,
char **pp_newserver,
char **pp_newshare,
bool force_encrypt,
const char *username,
const char *password,
const char *domain);
/******************************************************************** /********************************************************************
Ensure a connection is encrypted. Ensure a connection is encrypted.
********************************************************************/ ********************************************************************/
@ -241,7 +231,7 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
/* here's the fun part....to support 'msdfs proxy' shares /* here's the fun part....to support 'msdfs proxy' shares
(on Samba or windows) we have to issues a TRANS_GET_DFS_REFERRAL (on Samba or windows) we have to issues a TRANS_GET_DFS_REFERRAL
here before trying to connect to the original share. here before trying to connect to the original share.
check_dfs_proxy() will fail if it is a normal share. */ cli_check_msdfs_proxy() will fail if it is a normal share. */
if ((c->capabilities & CAP_DFS) && if ((c->capabilities & CAP_DFS) &&
cli_check_msdfs_proxy(ctx, c, sharename, cli_check_msdfs_proxy(ctx, c, sharename,
@ -984,7 +974,7 @@ bool cli_resolve_path(TALLOC_CTX *ctx,
/******************************************************************** /********************************************************************
********************************************************************/ ********************************************************************/
static bool cli_check_msdfs_proxy(TALLOC_CTX *ctx, bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
struct cli_state *cli, struct cli_state *cli,
const char *sharename, const char *sharename,
char **pp_newserver, char **pp_newserver,

View File

@ -7,6 +7,7 @@
Copyright (C) Tom Jansen (Ninja ISD) 2002 Copyright (C) Tom Jansen (Ninja ISD) 2002
Copyright (C) Derrell Lipman 2003-2008 Copyright (C) Derrell Lipman 2003-2008
Copyright (C) Jeremy Allison 2007, 2008 Copyright (C) Jeremy Allison 2007, 2008
Copyright (C) SATOH Fumiyasu <fumiyas@osstech.co.jp> 2009.
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -227,15 +228,16 @@ check_server_cache:
* info we need, unless the username and password were passed in. * info we need, unless the username and password were passed in.
*/ */
SMBCSRV * static SMBCSRV *
SMBC_server(TALLOC_CTX *ctx, SMBC_server_internal(TALLOC_CTX *ctx,
SMBCCTX *context, SMBCCTX *context,
bool connect_if_not_found, bool connect_if_not_found,
const char *server, const char *server,
const char *share, const char *share,
char **pp_workgroup, char **pp_workgroup,
char **pp_username, char **pp_username,
char **pp_password) char **pp_password,
bool *in_cache)
{ {
SMBCSRV *srv=NULL; SMBCSRV *srv=NULL;
char *workgroup = NULL; char *workgroup = NULL;
@ -250,9 +252,11 @@ SMBC_server(TALLOC_CTX *ctx,
uint32 fs_attrs = 0; uint32 fs_attrs = 0;
const char *username_used; const char *username_used;
NTSTATUS status; NTSTATUS status;
char *newserver, *newshare;
zero_sockaddr(&ss); zero_sockaddr(&ss);
ZERO_STRUCT(c); ZERO_STRUCT(c);
*in_cache = false;
if (server[0] == 0) { if (server[0] == 0) {
errno = EPERM; errno = EPERM;
@ -279,9 +283,18 @@ SMBC_server(TALLOC_CTX *ctx,
* disconnect if the requested share is not the same as the * disconnect if the requested share is not the same as the
* one that was already connected. * one that was already connected.
*/ */
/*
* Use srv->cli->desthost and srv->cli->share instead of
* server and share below to connect to the actual share,
* i.e., a normal share or a referred share from
* 'msdfs proxy' share.
*/
if (srv->cli->cnum == (uint16) -1) { if (srv->cli->cnum == (uint16) -1) {
/* Ensure we have accurate auth info */ /* Ensure we have accurate auth info */
SMBC_call_auth_fn(ctx, context, server, share, SMBC_call_auth_fn(ctx, context,
srv->cli->desthost,
srv->cli->share,
pp_workgroup, pp_workgroup,
pp_username, pp_username,
pp_password); pp_password);
@ -301,7 +314,7 @@ SMBC_server(TALLOC_CTX *ctx,
* tid. * tid.
*/ */
status = cli_tcon_andx(srv->cli, share, "?????", status = cli_tcon_andx(srv->cli, srv->cli->share, "?????",
*pp_password, *pp_password,
strlen(*pp_password)+1); strlen(*pp_password)+1);
if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(status)) {
@ -350,8 +363,8 @@ SMBC_server(TALLOC_CTX *ctx,
* server and share * server and share
*/ */
if (srv) { if (srv) {
srv->dev = (dev_t)(str_checksum(server) ^ srv->dev = (dev_t)(str_checksum(srv->cli->desthost) ^
str_checksum(share)); str_checksum(srv->cli->share));
} }
} }
} }
@ -360,6 +373,7 @@ SMBC_server(TALLOC_CTX *ctx,
if (srv) { if (srv) {
/* ... then we're done here. Give 'em what they came for. */ /* ... then we're done here. Give 'em what they came for. */
*in_cache = true;
goto done; goto done;
} }
@ -510,6 +524,32 @@ again:
DEBUG(4,(" session setup ok\n")); DEBUG(4,(" session setup ok\n"));
/* here's the fun part....to support 'msdfs proxy' shares
(on Samba or windows) we have to issues a TRANS_GET_DFS_REFERRAL
here before trying to connect to the original share.
cli_check_msdfs_proxy() will fail if it is a normal share. */
if ((c->capabilities & CAP_DFS) &&
cli_check_msdfs_proxy(ctx, c, share,
&newserver, &newshare,
/* FIXME: cli_check_msdfs_proxy() does
not support smbc_smb_encrypt_level type */
context->internal->smb_encryption_level ?
true : false,
*pp_username,
*pp_password,
*pp_workgroup)) {
cli_shutdown(c);
srv = SMBC_server_internal(ctx, context, connect_if_not_found,
newserver, newshare, pp_workgroup,
pp_username, pp_password, in_cache);
TALLOC_FREE(newserver);
TALLOC_FREE(newshare);
return srv;
}
/* must be a normal share */
status = cli_tcon_andx(c, share, "?????", *pp_password, status = cli_tcon_andx(c, share, "?????", *pp_password,
strlen(*pp_password)+1); strlen(*pp_password)+1);
if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(status)) {
@ -579,8 +619,9 @@ again:
srv = SMB_MALLOC_P(SMBCSRV); srv = SMB_MALLOC_P(SMBCSRV);
if (!srv) { if (!srv) {
cli_shutdown(c);
errno = ENOMEM; errno = ENOMEM;
goto failed; return NULL;
} }
ZERO_STRUCTP(srv); ZERO_STRUCTP(srv);
@ -590,26 +631,6 @@ again:
srv->no_pathinfo2 = False; srv->no_pathinfo2 = False;
srv->no_nt_session = False; srv->no_nt_session = False;
/* now add it to the cache (internal or external) */
/* Let the cache function set errno if it wants to */
errno = 0;
if (smbc_getFunctionAddCachedServer(context)(context, srv,
server, share,
*pp_workgroup,
*pp_username)) {
int saved_errno = errno;
DEBUG(3, (" Failed to add server to cache\n"));
errno = saved_errno;
if (errno == 0) {
errno = ENOMEM;
}
goto failed;
}
DEBUG(2, ("Server connect ok: //%s/%s: %p\n",
server, share, srv));
DLIST_ADD(context->internal->servers, srv);
done: done:
if (!pp_workgroup || !*pp_workgroup || !**pp_workgroup) { if (!pp_workgroup || !*pp_workgroup || !**pp_workgroup) {
workgroup = talloc_strdup(ctx, smbc_getWorkgroup(context)); workgroup = talloc_strdup(ctx, smbc_getWorkgroup(context));
@ -627,17 +648,56 @@ done:
*pp_password); *pp_password);
return srv; return srv;
}
SMBCSRV *
SMBC_server(TALLOC_CTX *ctx,
SMBCCTX *context,
bool connect_if_not_found,
const char *server,
const char *share,
char **pp_workgroup,
char **pp_username,
char **pp_password)
{
SMBCSRV *srv=NULL;
bool in_cache = false;
srv = SMBC_server_internal(ctx, context, connect_if_not_found,
server, share, pp_workgroup,
pp_username, pp_password, &in_cache);
failed:
cli_shutdown(c);
if (!srv) { if (!srv) {
return NULL; return NULL;
} }
if (in_cache) {
return srv;
}
/* Now add it to the cache (internal or external) */
/* Let the cache function set errno if it wants to */
errno = 0;
if (smbc_getFunctionAddCachedServer(context)(context, srv,
server, share,
*pp_workgroup,
*pp_username)) {
int saved_errno = errno;
DEBUG(3, (" Failed to add server to cache\n"));
errno = saved_errno;
if (errno == 0) {
errno = ENOMEM;
}
SAFE_FREE(srv); SAFE_FREE(srv);
return NULL; return NULL;
} }
DEBUG(2, ("Server connect ok: //%s/%s: %p\n",
server, share, srv));
DLIST_ADD(context->internal->servers, srv);
return srv;
}
/* /*
* Connect to a server for getting/setting attributes, possibly on an existing * Connect to a server for getting/setting attributes, possibly on an existing
* connection. This works similarly to SMBC_server(). * connection. This works similarly to SMBC_server().
@ -656,8 +716,23 @@ SMBC_attr_server(TALLOC_CTX *ctx,
struct cli_state *ipc_cli; struct cli_state *ipc_cli;
struct rpc_pipe_client *pipe_hnd; struct rpc_pipe_client *pipe_hnd;
NTSTATUS nt_status; NTSTATUS nt_status;
SMBCSRV *srv=NULL;
SMBCSRV *ipc_srv=NULL; SMBCSRV *ipc_srv=NULL;
/*
* Use srv->cli->desthost and srv->cli->share instead of
* server and share below to connect to the actual share,
* i.e., a normal share or a referred share from
* 'msdfs proxy' share.
*/
srv = SMBC_server(ctx, context, true, server, share,
pp_workgroup, pp_username, pp_password);
if (!srv) {
return NULL;
}
server = srv->cli->desthost;
share = srv->cli->share;
/* /*
* See if we've already created this special connection. Reference * See if we've already created this special connection. Reference
* our "special" share name '*IPC$', which is an impossible real share * our "special" share name '*IPC$', which is an impossible real share