From 922f61060c6a90bd197bfadabbf943e19318082b Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Fri, 20 Feb 2009 12:21:52 +0800 Subject: [PATCH] Make libsmbclient work with DFS Signed-off-by: Derrell Lipman (cherry picked from commit 8457e7bba4ef2ba479340829bb89a3a8772f958b) --- source/include/libsmbclient.h | 12 ++++++++++++ source/libsmb/libsmb_context.c | 37 +++++++++++++++++++++++++++++++++++++ source/libsmb/libsmb_dir.c | 27 +++++++++++++++++++++++++-- source/libsmb/libsmb_file.c | 2 +- source/libsmb/libsmb_path.c | 15 ++++++++++++++- source/libsmb/libsmb_server.c | 19 ++++++++++++++++++- source/libsmb/libsmb_stat.c | 2 +- 7 files changed, 108 insertions(+), 6 deletions(-) diff --git a/source/include/libsmbclient.h b/source/include/libsmbclient.h index f8a6c8a235e..efc471c85b4 100644 --- a/source/include/libsmbclient.h +++ b/source/include/libsmbclient.h @@ -2683,6 +2683,18 @@ smbc_set_credentials(char *workgroup, smbc_bool use_kerberos, char *signing_state); +/* + * Wrapper around smbc_set_credentials. + * Used to set correct credentials that will + * be used to connect to DFS target share + * in libsmbclient + */ + +void +smbc_set_credentials_with_fallback(SMBCCTX *ctx, + char *workgroup, + char *user, + char *password); /** * @ingroup structure diff --git a/source/libsmb/libsmb_context.c b/source/libsmb/libsmb_context.c index 3f8e0c573cb..c8a10794351 100644 --- a/source/libsmb/libsmb_context.c +++ b/source/libsmb/libsmb_context.c @@ -646,3 +646,40 @@ smbc_set_credentials(char *workgroup, set_global_myworkgroup(workgroup); cli_cm_set_credentials(); } + +void smbc_set_credentials_with_fallback(SMBCCTX *context, + char *workgroup, + char *user, + char *password) +{ + smbc_bool use_kerberos = false; + const char *signing_state = "off"; + + if (!context || !workgroup || !*workgroup + || !user || !*user || !password + || !*password) { + return; + } + + if (smbc_getOptionUseKerberos(context)) { + use_kerberos = True; + } + + if (lp_client_signing()) { + signing_state = "on"; + } + + if (lp_client_signing() == Required) { + signing_state = "force"; + } + + smbc_set_credentials(workgroup, + user, + password, + use_kerberos, + (char *)signing_state); + + if (smbc_getOptionFallbackAfterKerberos(context)) { + cli_cm_set_fallback_after_kerberos(); + } +} diff --git a/source/libsmb/libsmb_dir.c b/source/libsmb/libsmb_dir.c index 761b8055091..610cfcd3cf4 100644 --- a/source/libsmb/libsmb_dir.c +++ b/source/libsmb/libsmb_dir.c @@ -1501,6 +1501,8 @@ SMBC_chmod_ctx(SMBCCTX *context, char *user = NULL; char *password = NULL; char *workgroup = NULL; + char *targetpath = NULL; + struct cli_state *targetcli = NULL; char *path = NULL; uint16 mode; TALLOC_CTX *frame = talloc_stackframe(); @@ -1551,6 +1553,14 @@ SMBC_chmod_ctx(SMBCCTX *context, TALLOC_FREE(frame); return -1; /* errno set by SMBC_server */ } + + /*d_printf(">>>unlink: resolving %s\n", path);*/ + if (!cli_resolve_path(frame, "", srv->cli, path, + &targetcli, &targetpath)) { + d_printf("Could not resolve %s\n", path); + TALLOC_FREE(frame); + return -1; + } mode = 0; @@ -1559,8 +1569,8 @@ SMBC_chmod_ctx(SMBCCTX *context, if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM; if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN; - if (!cli_setatr(srv->cli, path, mode, 0)) { - errno = SMBC_errno(context, srv->cli); + if (!cli_setatr(targetcli, targetpath, mode, 0)) { + errno = SMBC_errno(context, targetcli); TALLOC_FREE(frame); return -1; } @@ -1901,6 +1911,12 @@ SMBC_rename_ctx(SMBCCTX *ocontext, } + /* set the credentials to make DFS work */ + smbc_set_credentials_with_fallback(ocontext, + workgroup, + user1, + password1); + /*d_printf(">>>rename: resolving %s\n", path1);*/ if (!cli_resolve_path(frame, "", srv->cli, path1, &targetcli1, &targetpath1)) { @@ -1908,6 +1924,13 @@ SMBC_rename_ctx(SMBCCTX *ocontext, TALLOC_FREE(frame); return -1; } + + /* set the credentials to make DFS work */ + smbc_set_credentials_with_fallback(ncontext, + workgroup, + user2, + password2); + /*d_printf(">>>rename: resolved path as %s\n", targetpath1);*/ /*d_printf(">>>rename: resolving %s\n", path2);*/ if (!cli_resolve_path(frame, "", srv->cli, path2, diff --git a/source/libsmb/libsmb_file.c b/source/libsmb/libsmb_file.c index e162aaa16b7..1bbb47daebe 100644 --- a/source/libsmb/libsmb_file.c +++ b/source/libsmb/libsmb_file.c @@ -382,7 +382,7 @@ SMBC_write_ctx(SMBCCTX *context, TALLOC_FREE(frame); return -1; } - + /*d_printf(">>>write: resolving %s\n", path);*/ if (!cli_resolve_path(frame, "", file->srv->cli, path, &targetcli, &targetpath)) { diff --git a/source/libsmb/libsmb_path.c b/source/libsmb/libsmb_path.c index 6d69924231b..3ea03446d89 100644 --- a/source/libsmb/libsmb_path.c +++ b/source/libsmb/libsmb_path.c @@ -233,6 +233,7 @@ SMBC_parse_path(TALLOC_CTX *ctx, char *s; const char *p; char *q, *r; + char *workgroup = NULL; int len; /* Ensure these returns are at least valid pointers. */ @@ -332,7 +333,6 @@ SMBC_parse_path(TALLOC_CTX *ctx, u = userinfo; if (strchr_m(u, ';')) { - char *workgroup; next_token_no_ltrim_talloc(ctx, &u, &workgroup, ";"); if (!workgroup) { return -1; @@ -394,6 +394,19 @@ decoding: (void) urldecode_talloc(ctx, pp_share, *pp_share); (void) urldecode_talloc(ctx, pp_user, *pp_user); (void) urldecode_talloc(ctx, pp_password, *pp_password); + + if (!workgroup) { + workgroup = talloc_strdup(ctx, smbc_getWorkgroup(context)); + } + if (!workgroup) { + return -1; + } + + /* set the credentials to make DFS work */ + smbc_set_credentials_with_fallback(context, + workgroup, + *pp_user, + *pp_password); return 0; } diff --git a/source/libsmb/libsmb_server.c b/source/libsmb/libsmb_server.c index 0c411ea85f1..6880f5c3426 100644 --- a/source/libsmb/libsmb_server.c +++ b/source/libsmb/libsmb_server.c @@ -238,6 +238,7 @@ SMBC_server(TALLOC_CTX *ctx, char **pp_password) { SMBCSRV *srv=NULL; + char *workgroup = NULL; struct cli_state *c; struct nmb_name called, calling; const char *server_n = server; @@ -359,7 +360,7 @@ SMBC_server(TALLOC_CTX *ctx, if (srv) { /* ... then we're done here. Give 'em what they came for. */ - return srv; + goto done; } /* If we're not asked to connect when a connection doesn't exist... */ @@ -598,6 +599,22 @@ again: server, share, srv)); DLIST_ADD(context->internal->servers, srv); +done: + if (!pp_workgroup || !*pp_workgroup || !**pp_workgroup) { + workgroup = talloc_strdup(ctx, smbc_getWorkgroup(context)); + } else { + workgroup = *pp_workgroup; + } + if(!workgroup) { + return NULL; + } + + /* set the credentials to make DFS work */ + smbc_set_credentials_with_fallback(context, + workgroup, + *pp_username, + *pp_password); + return srv; failed: diff --git a/source/libsmb/libsmb_stat.c b/source/libsmb/libsmb_stat.c index 186ef130bf7..64ddc780a8d 100644 --- a/source/libsmb/libsmb_stat.c +++ b/source/libsmb/libsmb_stat.c @@ -155,7 +155,7 @@ SMBC_stat_ctx(SMBCCTX *context, TALLOC_FREE(frame); return -1; } - + if (!user || user[0] == (char)0) { user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { -- 2.11.4.GIT