From 257b7b09298f7cb983b2f31b87fc5e46e0f62f0c Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Thu, 28 Feb 2008 11:23:20 -0500 Subject: Initial revamp of the libsmbclient interface. The libsmbclient interface has suffered from difficulty of improvement and feature enrichment without causing ABI breakage. Although there were a number of issues, the primary ones were: (a) the user of the library would manually manipulate the context structure members, meaning that nothing in the context structure could change other than adding stuff at the end; (b) there were three methods of setting options: setting bits in a flags field within the context structure, setting explicit options variables within an options structure in the context structure, and by calling the smbc_option_set() function; (c) the authentication callback did not traditionally provide enough information to the callee which required adding an option for a callback with a different signature, and now there are requests for even more information at the callback, requiring yet a third signature and option to set it (if we implement that feature). This commit provides a reorganization of the code which fixes (a) and (b). The context structure is now entirely opaque, and there are setter and getter functions for manipulating it. This makes maintaining ABI consistency much, much easier. Additionally, the options setting/getting has been unified into a single mechanism using smbc_option_set() and smbc_option_get(). Yet to be completed is a refactoring of the authentication callback (c). The test programs in examples/libsmbclient have been modified (if necessary; some applications require no changes at all) for the new API and a few have been minimally tested. Derrell (This used to be commit d4b4bae8ded824d06ad5ab0e219f71187ee5c771) --- source3/libsmb/libsmb_server.c | 675 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 675 insertions(+) create mode 100644 source3/libsmb/libsmb_server.c (limited to 'source3/libsmb/libsmb_server.c') diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c new file mode 100644 index 0000000000..978a843d30 --- /dev/null +++ b/source3/libsmb/libsmb_server.c @@ -0,0 +1,675 @@ +/* + Unix SMB/Netbios implementation. + SMB client library implementation + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Richard Sharpe 2000, 2002 + Copyright (C) John Terpstra 2000 + Copyright (C) Tom Jansen (Ninja ISD) 2002 + Copyright (C) Derrell Lipman 2003-2008 + Copyright (C) Jeremy Allison 2007, 2008 + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "libsmbclient.h" +#include "libsmb_internal.h" + + +/* + * Check a server for being alive and well. + * returns 0 if the server is in shape. Returns 1 on error + * + * Also useable outside libsmbclient to enable external cache + * to do some checks too. + */ +int +SMBC_check_server(SMBCCTX * context, + SMBCSRV * server) +{ + socklen_t size; + struct sockaddr addr; + + size = sizeof(addr); + return (getpeername(server->cli->fd, &addr, &size) == -1); +} + +/* + * Remove a server from the cached server list it's unused. + * On success, 0 is returned. 1 is returned if the server could not be removed. + * + * Also useable outside libsmbclient + */ +int +SMBC_remove_unused_server(SMBCCTX * context, + SMBCSRV * srv) +{ + SMBCFILE * file; + + /* are we being fooled ? */ + if (!context || !context->initialized || !srv) { + return 1; + } + + /* Check all open files/directories for a relation with this server */ + for (file = context->files; file; file = file->next) { + if (file->srv == srv) { + /* Still used */ + DEBUG(3, ("smbc_remove_usused_server: " + "%p still used by %p.\n", + srv, file)); + return 1; + } + } + + DLIST_REMOVE(context->servers, srv); + + cli_shutdown(srv->cli); + srv->cli = NULL; + + DEBUG(3, ("smbc_remove_usused_server: %p removed.\n", srv)); + + (context->cache.remove_cached_server_fn)(context, srv); + + SAFE_FREE(srv); + return 0; +} + +/**************************************************************** + * Call the auth_fn with fixed size (fstring) buffers. + ***************************************************************/ +void +SMBC_call_auth_fn(TALLOC_CTX *ctx, + SMBCCTX *context, + const char *server, + const char *share, + char **pp_workgroup, + char **pp_username, + char **pp_password) +{ + fstring workgroup; + fstring username; + fstring password; + + strlcpy(workgroup, *pp_workgroup, sizeof(workgroup)); + strlcpy(username, *pp_username, sizeof(username)); + strlcpy(password, *pp_password, sizeof(password)); + + (context->server.get_auth_data_fn)( + server, share, + workgroup, sizeof(workgroup), + username, sizeof(username), + password, sizeof(password)); + + TALLOC_FREE(*pp_workgroup); + TALLOC_FREE(*pp_username); + TALLOC_FREE(*pp_password); + + *pp_workgroup = talloc_strdup(ctx, workgroup); + *pp_username = talloc_strdup(ctx, username); + *pp_password = talloc_strdup(ctx, password); +} + + +void +SMBC_get_auth_data(const char *server, const char *share, + char *workgroup_buf, int workgroup_buf_len, + char *username_buf, int username_buf_len, + char *password_buf, int password_buf_len) +{ + /* Default function just uses provided data. Nothing to do. */ +} + + + +SMBCSRV * +SMBC_find_server(TALLOC_CTX *ctx, + SMBCCTX *context, + const char *server, + const char *share, + char **pp_workgroup, + char **pp_username, + char **pp_password) +{ + SMBCSRV *srv; + int auth_called = 0; + + check_server_cache: + + srv = (context->cache.get_cached_server_fn)(context, + server, share, + *pp_workgroup, + *pp_username); + + if (!auth_called && !srv && (!*pp_username || !(*pp_username)[0] || + !*pp_password || !(*pp_password)[0])) { + SMBC_call_auth_fn(ctx, context, server, share, + pp_workgroup, pp_username, pp_password); + + if (!pp_workgroup || !pp_username || !pp_password) { + return NULL; + } + + /* + * However, smbc_auth_fn may have picked up info relating to + * an existing connection, so try for an existing connection + * again ... + */ + auth_called = 1; + goto check_server_cache; + + } + + if (srv) { + if ((context->server.check_server_fn)(context, srv)) { + /* + * This server is no good anymore + * Try to remove it and check for more possible + * servers in the cache + */ + if ((context->server.remove_unused_server_fn)(context, + srv)) { + /* + * We could not remove the server completely, + * remove it from the cache so we will not get + * it again. It will be removed when the last + * file/dir is closed. + */ + (context->cache.remove_cached_server_fn)(context, + srv); + } + + /* + * Maybe there are more cached connections to this + * server + */ + goto check_server_cache; + } + + return srv; + } + + return NULL; +} + +/* + * Connect to a server, possibly on an existing connection + * + * Here, what we want to do is: If the server and username + * match an existing connection, reuse that, otherwise, establish a + * new connection. + * + * If we have to create a new connection, call the auth_fn to get the + * info we need, unless the username and password were passed in. + */ + +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; + struct cli_state *c; + struct nmb_name called, calling; + const char *server_n = server; + struct sockaddr_storage ss; + int tried_reverse = 0; + int port_try_first; + int port_try_next; + const char *username_used; + NTSTATUS status; + + zero_addr(&ss); + ZERO_STRUCT(c); + + if (server[0] == 0) { + errno = EPERM; + return NULL; + } + + /* Look for a cached connection */ + srv = SMBC_find_server(ctx, context, server, share, + pp_workgroup, pp_username, pp_password); + + /* + * If we found a connection and we're only allowed one share per + * server... + */ + if (srv && *share != '\0' && context->one_share_per_server) { + + /* + * ... then if there's no current connection to the share, + * connect to it. SMBC_find_server(), or rather the function + * pointed to by context->cache.get_cached_srv_fn which + * was called by SMBC_find_server(), will have issued a tree + * disconnect if the requested share is not the same as the + * one that was already connected. + */ + if (srv->cli->cnum == (uint16) -1) { + /* Ensure we have accurate auth info */ + SMBC_call_auth_fn(ctx, context, server, share, + pp_workgroup, pp_username, pp_password); + + if (!*pp_workgroup || !*pp_username || !*pp_password) { + errno = ENOMEM; + cli_shutdown(srv->cli); + srv->cli = NULL; + (context->cache.remove_cached_server_fn)(context, + srv); + return NULL; + } + + /* + * We don't need to renegotiate encryption + * here as the encryption context is not per + * tid. + */ + + if (!cli_send_tconX(srv->cli, share, "?????", + *pp_password, + strlen(*pp_password)+1)) { + + errno = SMBC_errno(context, srv->cli); + cli_shutdown(srv->cli); + srv->cli = NULL; + (context->cache.remove_cached_server_fn)(context, + srv); + srv = NULL; + } + + /* + * Regenerate the dev value since it's based on both + * server and share + */ + if (srv) { + srv->dev = (dev_t)(str_checksum(server) ^ + str_checksum(share)); + } + } + } + + /* If we have a connection... */ + if (srv) { + + /* ... then we're done here. Give 'em what they came for. */ + return srv; + } + + /* If we're not asked to connect when a connection doesn't exist... */ + if (! connect_if_not_found) { + /* ... then we're done here. */ + return NULL; + } + + if (!*pp_workgroup || !*pp_username || !*pp_password) { + errno = ENOMEM; + return NULL; + } + + make_nmb_name(&calling, context->netbios_name, 0x0); + make_nmb_name(&called , server, 0x20); + + DEBUG(4,("SMBC_server: server_n=[%s] server=[%s]\n", server_n, server)); + + DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server)); + + again: + + zero_addr(&ss); + + /* have to open a new connection */ + if ((c = cli_initialise()) == NULL) { + errno = ENOMEM; + return NULL; + } + + if (context->use_kerberos) { + c->use_kerberos = True; + } + if (context->fallback_after_kerberos) { + c->fallback_after_kerberos = True; + } + + c->timeout = context->timeout; + + /* + * Force use of port 139 for first try if share is $IPC, empty, or + * null, so browse lists can work + */ + if (share == NULL || *share == '\0' || strcmp(share, "IPC$") == 0) { + port_try_first = 139; + port_try_next = 445; + } else { + port_try_first = 445; + port_try_next = 139; + } + + c->port = port_try_first; + + status = cli_connect(c, server_n, &ss); + if (!NT_STATUS_IS_OK(status)) { + + /* First connection attempt failed. Try alternate port. */ + c->port = port_try_next; + + status = cli_connect(c, server_n, &ss); + if (!NT_STATUS_IS_OK(status)) { + cli_shutdown(c); + errno = ETIMEDOUT; + return NULL; + } + } + + if (!cli_session_request(c, &calling, &called)) { + cli_shutdown(c); + if (strcmp(called.name, "*SMBSERVER")) { + make_nmb_name(&called , "*SMBSERVER", 0x20); + goto again; + } else { /* Try one more time, but ensure we don't loop */ + + /* Only try this if server is an IP address ... */ + + if (is_ipaddress(server) && !tried_reverse) { + fstring remote_name; + struct sockaddr_storage rem_ss; + + if (!interpret_string_addr(&rem_ss, server, + NI_NUMERICHOST)) { + DEBUG(4, ("Could not convert IP address " + "%s to struct sockaddr_storage\n", + server)); + errno = ETIMEDOUT; + return NULL; + } + + tried_reverse++; /* Yuck */ + + if (name_status_find("*", 0, 0, &rem_ss, remote_name)) { + make_nmb_name(&called, remote_name, 0x20); + goto again; + } + } + } + errno = ETIMEDOUT; + return NULL; + } + + DEBUG(4,(" session request ok\n")); + + if (!cli_negprot(c)) { + cli_shutdown(c); + errno = ETIMEDOUT; + return NULL; + } + + username_used = *pp_username; + + if (!NT_STATUS_IS_OK(cli_session_setup(c, username_used, + *pp_password, strlen(*pp_password), + *pp_password, strlen(*pp_password), + *pp_workgroup))) { + + /* Failed. Try an anonymous login, if allowed by flags. */ + username_used = ""; + + if (context->no_auto_anonymous_login || + !NT_STATUS_IS_OK(cli_session_setup(c, username_used, + *pp_password, 1, + *pp_password, 0, + *pp_workgroup))) { + + cli_shutdown(c); + errno = EPERM; + return NULL; + } + } + + DEBUG(4,(" session setup ok\n")); + + if (!cli_send_tconX(c, share, "?????", + *pp_password, strlen(*pp_password)+1)) { + errno = SMBC_errno(context, c); + cli_shutdown(c); + return NULL; + } + + DEBUG(4,(" tconx ok\n")); + + if (context->smb_encryption_level) { + /* Attempt UNIX smb encryption. */ + if (!NT_STATUS_IS_OK(cli_force_encryption(c, + username_used, + *pp_password, + *pp_workgroup))) { + + /* + * context->smb_encryption_level == 1 + * means don't fail if encryption can't be negotiated, + * == 2 means fail if encryption can't be negotiated. + */ + + DEBUG(4,(" SMB encrypt failed\n")); + + if (context->smb_encryption_level == 2) { + cli_shutdown(c); + errno = EPERM; + return NULL; + } + } + DEBUG(4,(" SMB encrypt ok\n")); + } + + /* + * Ok, we have got a nice connection + * Let's allocate a server structure. + */ + + srv = SMB_MALLOC_P(SMBCSRV); + if (!srv) { + errno = ENOMEM; + goto failed; + } + + ZERO_STRUCTP(srv); + srv->cli = c; + srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share)); + srv->no_pathinfo = False; + srv->no_pathinfo2 = 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 ((context->cache.add_cached_server_fn)(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->servers, srv); + return srv; + + failed: + cli_shutdown(c); + if (!srv) { + return NULL; + } + + SAFE_FREE(srv); + return NULL; +} + +/* + * Connect to a server for getting/setting attributes, possibly on an existing + * connection. This works similarly to SMBC_server(). + */ +SMBCSRV * +SMBC_attr_server(TALLOC_CTX *ctx, + SMBCCTX *context, + const char *server, + const char *share, + char **pp_workgroup, + char **pp_username, + char **pp_password) +{ + int flags; + struct sockaddr_storage ss; + struct cli_state *ipc_cli; + struct rpc_pipe_client *pipe_hnd; + NTSTATUS nt_status; + SMBCSRV *ipc_srv=NULL; + + /* + * See if we've already created this special connection. Reference + * our "special" share name '*IPC$', which is an impossible real share + * name due to the leading asterisk. + */ + ipc_srv = SMBC_find_server(ctx, context, server, "*IPC$", + pp_workgroup, pp_username, pp_password); + if (!ipc_srv) { + + /* We didn't find a cached connection. Get the password */ + if (!*pp_password || (*pp_password)[0] == '\0') { + /* ... then retrieve it now. */ + SMBC_call_auth_fn(ctx, context, server, share, + pp_workgroup, pp_username, pp_password); + if (!*pp_workgroup || !*pp_username || !*pp_password) { + errno = ENOMEM; + return NULL; + } + } + + flags = 0; + if (context->use_kerberos) { + flags |= CLI_FULL_CONNECTION_USE_KERBEROS; + } + + zero_addr(&ss); + nt_status = cli_full_connection(&ipc_cli, + global_myname(), server, + &ss, 0, "IPC$", "?????", + *pp_username, + *pp_workgroup, + *pp_password, + flags, + Undefined, NULL); + if (! NT_STATUS_IS_OK(nt_status)) { + DEBUG(1,("cli_full_connection failed! (%s)\n", + nt_errstr(nt_status))); + errno = ENOTSUP; + return NULL; + } + + if (context->smb_encryption_level) { + /* Attempt UNIX smb encryption. */ + if (!NT_STATUS_IS_OK(cli_force_encryption(ipc_cli, + *pp_username, + *pp_password, + *pp_workgroup))) { + + /* + * context->smb_encryption_level == + * 1 means don't fail if encryption can't be + * negotiated, == 2 means fail if encryption + * can't be negotiated. + */ + + DEBUG(4,(" SMB encrypt failed on IPC$\n")); + + if (context->smb_encryption_level == 2) { + cli_shutdown(ipc_cli); + errno = EPERM; + return NULL; + } + } + DEBUG(4,(" SMB encrypt ok on IPC$\n")); + } + + ipc_srv = SMB_MALLOC_P(SMBCSRV); + if (!ipc_srv) { + errno = ENOMEM; + cli_shutdown(ipc_cli); + return NULL; + } + + ZERO_STRUCTP(ipc_srv); + ipc_srv->cli = ipc_cli; + + pipe_hnd = cli_rpc_pipe_open_noauth(ipc_srv->cli, + PI_LSARPC, + &nt_status); + if (!pipe_hnd) { + DEBUG(1, ("cli_nt_session_open fail!\n")); + errno = ENOTSUP; + cli_shutdown(ipc_srv->cli); + free(ipc_srv); + return NULL; + } + + /* + * Some systems don't support + * SEC_RIGHTS_MAXIMUM_ALLOWED, but NT sends 0x2000000 + * so we might as well do it too. + */ + + nt_status = rpccli_lsa_open_policy( + pipe_hnd, + talloc_tos(), + True, + GENERIC_EXECUTE_ACCESS, + &ipc_srv->pol); + + if (!NT_STATUS_IS_OK(nt_status)) { + errno = SMBC_errno(context, ipc_srv->cli); + cli_shutdown(ipc_srv->cli); + return NULL; + } + + /* now add it to the cache (internal or external) */ + + errno = 0; /* let cache function set errno if it likes */ + if ((context->cache.add_cached_server_fn)(context, ipc_srv, + server, + "*IPC$", + *pp_workgroup, + *pp_username)) { + DEBUG(3, (" Failed to add server to cache\n")); + if (errno == 0) { + errno = ENOMEM; + } + cli_shutdown(ipc_srv->cli); + free(ipc_srv); + return NULL; + } + + DLIST_ADD(context->servers, ipc_srv); + } + + return ipc_srv; +} -- cgit From 4ba42cbe0f6bbd25848786e1a87c06aca79b98ea Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Fri, 29 Feb 2008 13:34:35 -0500 Subject: Modified revamp of the libsmbclient interface. Given the tacit (if that) approval by some people, and clear disapproval by others for my proposed clean-up and reorganization of libsmbclient, I've come up with a slightly different approach. This commit changes back to the original libsmbclient.h SMBCCTX structure which will maintain ABI compatibility. I retain, here, the setter and getter functions which all new code should use. Older programs already compiled should continue to work fine. Older programs being recompiled will encounter compile-time errors (intentionally!) so that the code can be corrected to use the setter/getter interfaces. Although this doesn't clean up the interface in the way I had wanted, the code reorganization and requirement for new programs to use the setters and getters allows future progress to be made on libsmbclient without further muddying up the interface, while retaining the ABI compatibility that was the big issue causing disapproval. I hope that this compromise is adequate. Derrell (This used to be commit 56429a3d60b2a48963342f6340b3c01469a892c6) --- source3/libsmb/libsmb_server.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'source3/libsmb/libsmb_server.c') diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c index 978a843d30..70e0d57273 100644 --- a/source3/libsmb/libsmb_server.c +++ b/source3/libsmb/libsmb_server.c @@ -58,12 +58,12 @@ SMBC_remove_unused_server(SMBCCTX * context, SMBCFILE * file; /* are we being fooled ? */ - if (!context || !context->initialized || !srv) { + if (!context || !context->internal->initialized || !srv) { return 1; } /* Check all open files/directories for a relation with this server */ - for (file = context->files; file; file = file->next) { + for (file = context->internal->files; file; file = file->next) { if (file->srv == srv) { /* Still used */ DEBUG(3, ("smbc_remove_usused_server: " @@ -73,7 +73,7 @@ SMBC_remove_unused_server(SMBCCTX * context, } } - DLIST_REMOVE(context->servers, srv); + DLIST_REMOVE(context->internal->servers, srv); cli_shutdown(srv->cli); srv->cli = NULL; @@ -251,7 +251,7 @@ SMBC_server(TALLOC_CTX *ctx, * If we found a connection and we're only allowed one share per * server... */ - if (srv && *share != '\0' && context->one_share_per_server) { + if (srv && *share != '\0' && context->internal->one_share_per_server) { /* * ... then if there's no current connection to the share, @@ -322,7 +322,7 @@ SMBC_server(TALLOC_CTX *ctx, return NULL; } - make_nmb_name(&calling, context->netbios_name, 0x0); + make_nmb_name(&calling, context->config.netbios_name, 0x0); make_nmb_name(&called , server, 0x20); DEBUG(4,("SMBC_server: server_n=[%s] server=[%s]\n", server_n, server)); @@ -339,14 +339,14 @@ SMBC_server(TALLOC_CTX *ctx, return NULL; } - if (context->use_kerberos) { + if (context->flags.bits & SMB_CTX_FLAG_USE_KERBEROS) { c->use_kerberos = True; } - if (context->fallback_after_kerberos) { + if (context->flags.bits & SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS) { c->fallback_after_kerberos = True; } - c->timeout = context->timeout; + c->timeout = context->config.timeout; /* * Force use of port 139 for first try if share is $IPC, empty, or @@ -428,7 +428,8 @@ SMBC_server(TALLOC_CTX *ctx, /* Failed. Try an anonymous login, if allowed by flags. */ username_used = ""; - if (context->no_auto_anonymous_login || + if ((context->flags.bits & + SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON) || !NT_STATUS_IS_OK(cli_session_setup(c, username_used, *pp_password, 1, *pp_password, 0, @@ -451,7 +452,7 @@ SMBC_server(TALLOC_CTX *ctx, DEBUG(4,(" tconx ok\n")); - if (context->smb_encryption_level) { + if (context->internal->smb_encryption_level) { /* Attempt UNIX smb encryption. */ if (!NT_STATUS_IS_OK(cli_force_encryption(c, username_used, @@ -466,7 +467,7 @@ SMBC_server(TALLOC_CTX *ctx, DEBUG(4,(" SMB encrypt failed\n")); - if (context->smb_encryption_level == 2) { + if (context->internal->smb_encryption_level == 2) { cli_shutdown(c); errno = EPERM; return NULL; @@ -512,7 +513,7 @@ SMBC_server(TALLOC_CTX *ctx, DEBUG(2, ("Server connect ok: //%s/%s: %p\n", server, share, srv)); - DLIST_ADD(context->servers, srv); + DLIST_ADD(context->internal->servers, srv); return srv; failed: @@ -566,7 +567,7 @@ SMBC_attr_server(TALLOC_CTX *ctx, } flags = 0; - if (context->use_kerberos) { + if (context->flags.bits & SMB_CTX_FLAG_USE_KERBEROS) { flags |= CLI_FULL_CONNECTION_USE_KERBEROS; } @@ -586,7 +587,7 @@ SMBC_attr_server(TALLOC_CTX *ctx, return NULL; } - if (context->smb_encryption_level) { + if (context->internal->smb_encryption_level) { /* Attempt UNIX smb encryption. */ if (!NT_STATUS_IS_OK(cli_force_encryption(ipc_cli, *pp_username, @@ -602,7 +603,7 @@ SMBC_attr_server(TALLOC_CTX *ctx, DEBUG(4,(" SMB encrypt failed on IPC$\n")); - if (context->smb_encryption_level == 2) { + if (context->internal->smb_encryption_level == 2) { cli_shutdown(ipc_cli); errno = EPERM; return NULL; @@ -668,7 +669,7 @@ SMBC_attr_server(TALLOC_CTX *ctx, return NULL; } - DLIST_ADD(context->servers, ipc_srv); + DLIST_ADD(context->internal->servers, ipc_srv); } return ipc_srv; -- cgit From 223940d9a887c5b98a5c873797302a6a9407ad7f Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Sat, 1 Mar 2008 20:44:21 -0500 Subject: Additional revamped libsmbclient documentation - Ensured that all public functions have documentation in libsmbclient.h - Reformatted for "proper" indentation - Re-added temporarily-disabled alternate authentication function capability Derrell (This used to be commit 64b7150d92849a1e1e2416b9dcc12fae8d6bea99) --- source3/libsmb/libsmb_server.c | 275 +++++++++++++++++++++-------------------- 1 file changed, 142 insertions(+), 133 deletions(-) (limited to 'source3/libsmb/libsmb_server.c') diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c index 70e0d57273..4f51388870 100644 --- a/source3/libsmb/libsmb_server.c +++ b/source3/libsmb/libsmb_server.c @@ -40,7 +40,7 @@ SMBC_check_server(SMBCCTX * context, { socklen_t size; struct sockaddr addr; - + size = sizeof(addr); return (getpeername(server->cli->fd, &addr, &size) == -1); } @@ -56,12 +56,12 @@ SMBC_remove_unused_server(SMBCCTX * context, SMBCSRV * srv) { SMBCFILE * file; - + /* are we being fooled ? */ if (!context || !context->internal->initialized || !srv) { return 1; } - + /* Check all open files/directories for a relation with this server */ for (file = context->internal->files; file; file = file->next) { if (file->srv == srv) { @@ -72,16 +72,16 @@ SMBC_remove_unused_server(SMBCCTX * context, return 1; } } - + DLIST_REMOVE(context->internal->servers, srv); - + cli_shutdown(srv->cli); srv->cli = NULL; - + DEBUG(3, ("smbc_remove_usused_server: %p removed.\n", srv)); - + (context->cache.remove_cached_server_fn)(context, srv); - + SAFE_FREE(srv); return 0; } @@ -101,21 +101,21 @@ SMBC_call_auth_fn(TALLOC_CTX *ctx, fstring workgroup; fstring username; fstring password; - + strlcpy(workgroup, *pp_workgroup, sizeof(workgroup)); strlcpy(username, *pp_username, sizeof(username)); strlcpy(password, *pp_password, sizeof(password)); - + (context->server.get_auth_data_fn)( server, share, workgroup, sizeof(workgroup), username, sizeof(username), password, sizeof(password)); - + TALLOC_FREE(*pp_workgroup); TALLOC_FREE(*pp_username); TALLOC_FREE(*pp_password); - + *pp_workgroup = talloc_strdup(ctx, workgroup); *pp_username = talloc_strdup(ctx, username); *pp_password = talloc_strdup(ctx, password); @@ -144,23 +144,23 @@ SMBC_find_server(TALLOC_CTX *ctx, { SMBCSRV *srv; int auth_called = 0; - - check_server_cache: - + +check_server_cache: + srv = (context->cache.get_cached_server_fn)(context, server, share, *pp_workgroup, *pp_username); - + if (!auth_called && !srv && (!*pp_username || !(*pp_username)[0] || - !*pp_password || !(*pp_password)[0])) { + !*pp_password || !(*pp_password)[0])) { SMBC_call_auth_fn(ctx, context, server, share, - pp_workgroup, pp_username, pp_password); - + pp_workgroup, pp_username, pp_password); + if (!pp_workgroup || !pp_username || !pp_password) { return NULL; } - + /* * However, smbc_auth_fn may have picked up info relating to * an existing connection, so try for an existing connection @@ -168,9 +168,9 @@ SMBC_find_server(TALLOC_CTX *ctx, */ auth_called = 1; goto check_server_cache; - + } - + if (srv) { if ((context->server.check_server_fn)(context, srv)) { /* @@ -189,17 +189,17 @@ SMBC_find_server(TALLOC_CTX *ctx, (context->cache.remove_cached_server_fn)(context, srv); } - + /* * Maybe there are more cached connections to this * server */ goto check_server_cache; } - + return srv; } - + return NULL; } @@ -234,25 +234,25 @@ SMBC_server(TALLOC_CTX *ctx, int port_try_next; const char *username_used; NTSTATUS status; - + zero_addr(&ss); ZERO_STRUCT(c); - + if (server[0] == 0) { errno = EPERM; return NULL; } - + /* Look for a cached connection */ srv = SMBC_find_server(ctx, context, server, share, - pp_workgroup, pp_username, pp_password); - + pp_workgroup, pp_username, pp_password); + /* * If we found a connection and we're only allowed one share per * server... */ - if (srv && *share != '\0' && context->internal->one_share_per_server) { - + if (srv && *share != '\0' && context->options.one_share_per_server) { + /* * ... then if there's no current connection to the share, * connect to it. SMBC_find_server(), or rather the function @@ -264,8 +264,10 @@ SMBC_server(TALLOC_CTX *ctx, if (srv->cli->cnum == (uint16) -1) { /* Ensure we have accurate auth info */ SMBC_call_auth_fn(ctx, context, server, share, - pp_workgroup, pp_username, pp_password); - + pp_workgroup, + pp_username, + pp_password); + if (!*pp_workgroup || !*pp_username || !*pp_password) { errno = ENOMEM; cli_shutdown(srv->cli); @@ -274,17 +276,17 @@ SMBC_server(TALLOC_CTX *ctx, srv); return NULL; } - + /* * We don't need to renegotiate encryption * here as the encryption context is not per * tid. */ - + if (!cli_send_tconX(srv->cli, share, "?????", - *pp_password, - strlen(*pp_password)+1)) { - + *pp_password, + strlen(*pp_password)+1)) { + errno = SMBC_errno(context, srv->cli); cli_shutdown(srv->cli); srv->cli = NULL; @@ -292,7 +294,7 @@ SMBC_server(TALLOC_CTX *ctx, srv); srv = NULL; } - + /* * Regenerate the dev value since it's based on both * server and share @@ -303,51 +305,51 @@ SMBC_server(TALLOC_CTX *ctx, } } } - + /* If we have a connection... */ if (srv) { - + /* ... then we're done here. Give 'em what they came for. */ return srv; } - + /* If we're not asked to connect when a connection doesn't exist... */ if (! connect_if_not_found) { /* ... then we're done here. */ return NULL; } - + if (!*pp_workgroup || !*pp_username || !*pp_password) { errno = ENOMEM; return NULL; } - + make_nmb_name(&calling, context->config.netbios_name, 0x0); make_nmb_name(&called , server, 0x20); - + DEBUG(4,("SMBC_server: server_n=[%s] server=[%s]\n", server_n, server)); - + DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server)); - - again: - + +again: + zero_addr(&ss); - + /* have to open a new connection */ if ((c = cli_initialise()) == NULL) { errno = ENOMEM; return NULL; } - + if (context->flags.bits & SMB_CTX_FLAG_USE_KERBEROS) { c->use_kerberos = True; } if (context->flags.bits & SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS) { c->fallback_after_kerberos = True; } - + c->timeout = context->config.timeout; - + /* * Force use of port 139 for first try if share is $IPC, empty, or * null, so browse lists can work @@ -359,15 +361,15 @@ SMBC_server(TALLOC_CTX *ctx, port_try_first = 445; port_try_next = 139; } - + c->port = port_try_first; - + status = cli_connect(c, server_n, &ss); if (!NT_STATUS_IS_OK(status)) { - + /* First connection attempt failed. Try alternate port. */ c->port = port_try_next; - + status = cli_connect(c, server_n, &ss); if (!NT_STATUS_IS_OK(status)) { cli_shutdown(c); @@ -375,33 +377,36 @@ SMBC_server(TALLOC_CTX *ctx, return NULL; } } - + if (!cli_session_request(c, &calling, &called)) { cli_shutdown(c); if (strcmp(called.name, "*SMBSERVER")) { make_nmb_name(&called , "*SMBSERVER", 0x20); goto again; } else { /* Try one more time, but ensure we don't loop */ - + /* Only try this if server is an IP address ... */ - + if (is_ipaddress(server) && !tried_reverse) { fstring remote_name; struct sockaddr_storage rem_ss; - + if (!interpret_string_addr(&rem_ss, server, - NI_NUMERICHOST)) { + NI_NUMERICHOST)) { DEBUG(4, ("Could not convert IP address " - "%s to struct sockaddr_storage\n", - server)); + "%s to struct sockaddr_storage\n", + server)); errno = ETIMEDOUT; return NULL; } - + tried_reverse++; /* Yuck */ - - if (name_status_find("*", 0, 0, &rem_ss, remote_name)) { - make_nmb_name(&called, remote_name, 0x20); + + if (name_status_find("*", 0, 0, + &rem_ss, remote_name)) { + make_nmb_name(&called, + remote_name, + 0x20); goto again; } } @@ -409,64 +414,66 @@ SMBC_server(TALLOC_CTX *ctx, errno = ETIMEDOUT; return NULL; } - + DEBUG(4,(" session request ok\n")); - + if (!cli_negprot(c)) { cli_shutdown(c); errno = ETIMEDOUT; return NULL; } - + username_used = *pp_username; - + if (!NT_STATUS_IS_OK(cli_session_setup(c, username_used, - *pp_password, strlen(*pp_password), - *pp_password, strlen(*pp_password), + *pp_password, + strlen(*pp_password), + *pp_password, + strlen(*pp_password), *pp_workgroup))) { - + /* Failed. Try an anonymous login, if allowed by flags. */ username_used = ""; - + if ((context->flags.bits & SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON) || !NT_STATUS_IS_OK(cli_session_setup(c, username_used, *pp_password, 1, *pp_password, 0, *pp_workgroup))) { - + cli_shutdown(c); errno = EPERM; return NULL; } } - + DEBUG(4,(" session setup ok\n")); - + if (!cli_send_tconX(c, share, "?????", *pp_password, strlen(*pp_password)+1)) { errno = SMBC_errno(context, c); cli_shutdown(c); return NULL; } - + DEBUG(4,(" tconx ok\n")); - + if (context->internal->smb_encryption_level) { /* Attempt UNIX smb encryption. */ if (!NT_STATUS_IS_OK(cli_force_encryption(c, - username_used, - *pp_password, - *pp_workgroup))) { - + username_used, + *pp_password, + *pp_workgroup))) { + /* * context->smb_encryption_level == 1 * means don't fail if encryption can't be negotiated, * == 2 means fail if encryption can't be negotiated. */ - + DEBUG(4,(" SMB encrypt failed\n")); - + if (context->internal->smb_encryption_level == 2) { cli_shutdown(c); errno = EPERM; @@ -475,25 +482,25 @@ SMBC_server(TALLOC_CTX *ctx, } DEBUG(4,(" SMB encrypt ok\n")); } - + /* * Ok, we have got a nice connection * Let's allocate a server structure. */ - + srv = SMB_MALLOC_P(SMBCSRV); if (!srv) { errno = ENOMEM; goto failed; } - + ZERO_STRUCTP(srv); srv->cli = c; srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share)); srv->no_pathinfo = False; srv->no_pathinfo2 = 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; @@ -509,19 +516,19 @@ SMBC_server(TALLOC_CTX *ctx, } goto failed; } - + DEBUG(2, ("Server connect ok: //%s/%s: %p\n", server, share, srv)); - + DLIST_ADD(context->internal->servers, srv); return srv; - - failed: + +failed: cli_shutdown(c); if (!srv) { return NULL; } - + SAFE_FREE(srv); return NULL; } @@ -545,32 +552,34 @@ SMBC_attr_server(TALLOC_CTX *ctx, struct rpc_pipe_client *pipe_hnd; NTSTATUS nt_status; SMBCSRV *ipc_srv=NULL; - + /* * See if we've already created this special connection. Reference * our "special" share name '*IPC$', which is an impossible real share * name due to the leading asterisk. */ ipc_srv = SMBC_find_server(ctx, context, server, "*IPC$", - pp_workgroup, pp_username, pp_password); + pp_workgroup, pp_username, pp_password); if (!ipc_srv) { - + /* We didn't find a cached connection. Get the password */ if (!*pp_password || (*pp_password)[0] == '\0') { /* ... then retrieve it now. */ SMBC_call_auth_fn(ctx, context, server, share, - pp_workgroup, pp_username, pp_password); + pp_workgroup, + pp_username, + pp_password); if (!*pp_workgroup || !*pp_username || !*pp_password) { errno = ENOMEM; return NULL; } } - + flags = 0; if (context->flags.bits & SMB_CTX_FLAG_USE_KERBEROS) { flags |= CLI_FULL_CONNECTION_USE_KERBEROS; } - + zero_addr(&ss); nt_status = cli_full_connection(&ipc_cli, global_myname(), server, @@ -586,23 +595,23 @@ SMBC_attr_server(TALLOC_CTX *ctx, errno = ENOTSUP; return NULL; } - + if (context->internal->smb_encryption_level) { /* Attempt UNIX smb encryption. */ if (!NT_STATUS_IS_OK(cli_force_encryption(ipc_cli, - *pp_username, - *pp_password, - *pp_workgroup))) { - + *pp_username, + *pp_password, + *pp_workgroup))) { + /* * context->smb_encryption_level == * 1 means don't fail if encryption can't be * negotiated, == 2 means fail if encryption * can't be negotiated. */ - + DEBUG(4,(" SMB encrypt failed on IPC$\n")); - + if (context->internal->smb_encryption_level == 2) { cli_shutdown(ipc_cli); errno = EPERM; @@ -611,49 +620,49 @@ SMBC_attr_server(TALLOC_CTX *ctx, } DEBUG(4,(" SMB encrypt ok on IPC$\n")); } - + ipc_srv = SMB_MALLOC_P(SMBCSRV); if (!ipc_srv) { errno = ENOMEM; cli_shutdown(ipc_cli); return NULL; } - + ZERO_STRUCTP(ipc_srv); ipc_srv->cli = ipc_cli; - + pipe_hnd = cli_rpc_pipe_open_noauth(ipc_srv->cli, PI_LSARPC, &nt_status); if (!pipe_hnd) { - DEBUG(1, ("cli_nt_session_open fail!\n")); - errno = ENOTSUP; - cli_shutdown(ipc_srv->cli); - free(ipc_srv); - return NULL; + DEBUG(1, ("cli_nt_session_open fail!\n")); + errno = ENOTSUP; + cli_shutdown(ipc_srv->cli); + free(ipc_srv); + return NULL; } - + /* * Some systems don't support * SEC_RIGHTS_MAXIMUM_ALLOWED, but NT sends 0x2000000 * so we might as well do it too. */ - + nt_status = rpccli_lsa_open_policy( - pipe_hnd, - talloc_tos(), - True, - GENERIC_EXECUTE_ACCESS, - &ipc_srv->pol); - + pipe_hnd, + talloc_tos(), + True, + GENERIC_EXECUTE_ACCESS, + &ipc_srv->pol); + if (!NT_STATUS_IS_OK(nt_status)) { - errno = SMBC_errno(context, ipc_srv->cli); - cli_shutdown(ipc_srv->cli); - return NULL; + errno = SMBC_errno(context, ipc_srv->cli); + cli_shutdown(ipc_srv->cli); + return NULL; } - + /* now add it to the cache (internal or external) */ - + errno = 0; /* let cache function set errno if it likes */ if ((context->cache.add_cached_server_fn)(context, ipc_srv, server, @@ -668,9 +677,9 @@ SMBC_attr_server(TALLOC_CTX *ctx, free(ipc_srv); return NULL; } - + DLIST_ADD(context->internal->servers, ipc_srv); } - + return ipc_srv; } -- cgit From 1363ee9d65965704f716965c6cbcfc0693ca2401 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Mon, 3 Mar 2008 18:13:33 -0500 Subject: Continued revamping of libsmbclient. - James suggested using gcc's "deprecated" attribute to mark the context structure fields to generate warnings. This creates a scenario with the best of all worlds. I'm able to move to an organization that more easily allows future enhancements, while avoiding any mandatory changes by applications. Thanks, James! - Updated WHATSNEW.txt so that it accurately reflects the current state of affairs. Derrell (This used to be commit a67f96fbe9683b46c2149f7cb439d13f7f0e6ecd) --- source3/libsmb/libsmb_server.c | 75 +++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 37 deletions(-) (limited to 'source3/libsmb/libsmb_server.c') diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c index 4f51388870..64eb1ea584 100644 --- a/source3/libsmb/libsmb_server.c +++ b/source3/libsmb/libsmb_server.c @@ -80,7 +80,7 @@ SMBC_remove_unused_server(SMBCCTX * context, DEBUG(3, ("smbc_remove_usused_server: %p removed.\n", srv)); - (context->cache.remove_cached_server_fn)(context, srv); + smbc_getFunctionRemoveCachedServer(context)(context, srv); SAFE_FREE(srv); return 0; @@ -106,11 +106,10 @@ SMBC_call_auth_fn(TALLOC_CTX *ctx, strlcpy(username, *pp_username, sizeof(username)); strlcpy(password, *pp_password, sizeof(password)); - (context->server.get_auth_data_fn)( - server, share, - workgroup, sizeof(workgroup), - username, sizeof(username), - password, sizeof(password)); + smbc_getFunctionAuthData(context)(server, share, + workgroup, sizeof(workgroup), + username, sizeof(username), + password, sizeof(password)); TALLOC_FREE(*pp_workgroup); TALLOC_FREE(*pp_username); @@ -147,10 +146,10 @@ SMBC_find_server(TALLOC_CTX *ctx, check_server_cache: - srv = (context->cache.get_cached_server_fn)(context, - server, share, - *pp_workgroup, - *pp_username); + srv = smbc_getFunctionGetCachedServer(context)(context, + server, share, + *pp_workgroup, + *pp_username); if (!auth_called && !srv && (!*pp_username || !(*pp_username)[0] || !*pp_password || !(*pp_password)[0])) { @@ -172,22 +171,22 @@ check_server_cache: } if (srv) { - if ((context->server.check_server_fn)(context, srv)) { + if (smbc_getFunctionCheckServer(context)(context, srv)) { /* * This server is no good anymore * Try to remove it and check for more possible * servers in the cache */ - if ((context->server.remove_unused_server_fn)(context, - srv)) { + if (smbc_getFunctionRemoveUnusedServer(context)(context, + srv)) { /* * We could not remove the server completely, * remove it from the cache so we will not get * it again. It will be removed when the last * file/dir is closed. */ - (context->cache.remove_cached_server_fn)(context, - srv); + smbc_getFunctionRemoveCachedServer(context)(context, + srv); } /* @@ -251,12 +250,14 @@ SMBC_server(TALLOC_CTX *ctx, * If we found a connection and we're only allowed one share per * server... */ - if (srv && *share != '\0' && context->options.one_share_per_server) { + if (srv && + *share != '\0' && + smbc_getOptionOneSharePerServer(context)) { /* * ... then if there's no current connection to the share, * connect to it. SMBC_find_server(), or rather the function - * pointed to by context->cache.get_cached_srv_fn which + * pointed to by context->get_cached_srv_fn which * was called by SMBC_find_server(), will have issued a tree * disconnect if the requested share is not the same as the * one that was already connected. @@ -272,8 +273,8 @@ SMBC_server(TALLOC_CTX *ctx, errno = ENOMEM; cli_shutdown(srv->cli); srv->cli = NULL; - (context->cache.remove_cached_server_fn)(context, - srv); + smbc_getFunctionRemoveCachedServer(context)(context, + srv); return NULL; } @@ -290,8 +291,8 @@ SMBC_server(TALLOC_CTX *ctx, errno = SMBC_errno(context, srv->cli); cli_shutdown(srv->cli); srv->cli = NULL; - (context->cache.remove_cached_server_fn)(context, - srv); + smbc_getFunctionRemoveCachedServer(context)(context, + srv); srv = NULL; } @@ -324,7 +325,7 @@ SMBC_server(TALLOC_CTX *ctx, return NULL; } - make_nmb_name(&calling, context->config.netbios_name, 0x0); + make_nmb_name(&calling, smbc_getNetbiosName(context), 0x0); make_nmb_name(&called , server, 0x20); DEBUG(4,("SMBC_server: server_n=[%s] server=[%s]\n", server_n, server)); @@ -341,14 +342,15 @@ again: return NULL; } - if (context->flags.bits & SMB_CTX_FLAG_USE_KERBEROS) { + if (smbc_getOptionUseKerberos(context)) { c->use_kerberos = True; } - if (context->flags.bits & SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS) { + + if (smbc_getOptionFallbackAfterKerberos(context)) { c->fallback_after_kerberos = True; } - c->timeout = context->config.timeout; + c->timeout = smbc_getTimeout(context); /* * Force use of port 139 for first try if share is $IPC, empty, or @@ -435,8 +437,7 @@ again: /* Failed. Try an anonymous login, if allowed by flags. */ username_used = ""; - if ((context->flags.bits & - SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON) || + if (smbc_getOptionNoAutoAnonymousLogin(context) || !NT_STATUS_IS_OK(cli_session_setup(c, username_used, *pp_password, 1, *pp_password, 0, @@ -504,10 +505,10 @@ again: /* now add it to the cache (internal or external) */ /* Let the cache function set errno if it wants to */ errno = 0; - if ((context->cache.add_cached_server_fn)(context, srv, - server, share, - *pp_workgroup, - *pp_username)) { + 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; @@ -576,7 +577,7 @@ SMBC_attr_server(TALLOC_CTX *ctx, } flags = 0; - if (context->flags.bits & SMB_CTX_FLAG_USE_KERBEROS) { + if (smbc_getOptionUseKerberos(context)) { flags |= CLI_FULL_CONNECTION_USE_KERBEROS; } @@ -664,11 +665,11 @@ SMBC_attr_server(TALLOC_CTX *ctx, /* now add it to the cache (internal or external) */ errno = 0; /* let cache function set errno if it likes */ - if ((context->cache.add_cached_server_fn)(context, ipc_srv, - server, - "*IPC$", - *pp_workgroup, - *pp_username)) { + if (smbc_getFunctionAddCachedServer(context)(context, ipc_srv, + server, + "*IPC$", + *pp_workgroup, + *pp_username)) { DEBUG(3, (" Failed to add server to cache\n")); if (errno == 0) { errno = ENOMEM; -- cgit From 5b80b9340fb64413f68d625cf5ca57344c0adbd7 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Thu, 6 Mar 2008 09:00:37 -0500 Subject: Check for NULL pointers before dereferencing them. (This used to be commit 6f65390cec218a6aac4370ee381f30439617dcec) --- source3/libsmb/libsmb_server.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/libsmb/libsmb_server.c') diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c index 64eb1ea584..37612c6e39 100644 --- a/source3/libsmb/libsmb_server.c +++ b/source3/libsmb/libsmb_server.c @@ -144,6 +144,10 @@ SMBC_find_server(TALLOC_CTX *ctx, SMBCSRV *srv; int auth_called = 0; + if (!pp_workgroup || !pp_username || !pp_password) { + return NULL; + } + check_server_cache: srv = smbc_getFunctionGetCachedServer(context)(context, @@ -156,10 +160,6 @@ check_server_cache: SMBC_call_auth_fn(ctx, context, server, share, pp_workgroup, pp_username, pp_password); - if (!pp_workgroup || !pp_username || !pp_password) { - return NULL; - } - /* * However, smbc_auth_fn may have picked up info relating to * an existing connection, so try for an existing connection -- cgit From 8b0783072aad83f5a2ce10737ca9d3077af95bf9 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Mon, 17 Mar 2008 11:34:25 -0400 Subject: Fix use of AuthDataWithContext capability During my initial plans for, and the subsequent discussion of a more significant change to the API for libsmbclient, I had removed the AuthDataWithContext usage, in favor of a more generalized planned interface. When the API returned to its original state, I neglected to reinsert this code. Use of an authentication function with the context can be tested using examples/libsmbclient/testbrowse -C Derrell (This used to be commit 38eab68dfb2d8abe8ad00f5a86fc54c778d0d303) --- source3/libsmb/libsmb_server.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'source3/libsmb/libsmb_server.c') diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c index 37612c6e39..7af5ca3a24 100644 --- a/source3/libsmb/libsmb_server.c +++ b/source3/libsmb/libsmb_server.c @@ -101,15 +101,29 @@ SMBC_call_auth_fn(TALLOC_CTX *ctx, fstring workgroup; fstring username; fstring password; + smbc_get_auth_data_with_context_fn auth_with_context_fn; strlcpy(workgroup, *pp_workgroup, sizeof(workgroup)); strlcpy(username, *pp_username, sizeof(username)); strlcpy(password, *pp_password, sizeof(password)); - smbc_getFunctionAuthData(context)(server, share, - workgroup, sizeof(workgroup), - username, sizeof(username), - password, sizeof(password)); + /* See if there's an authentication with context function provided */ + auth_with_context_fn = smbc_getFunctionAuthDataWithContext(context); + if (auth_with_context_fn) + { + (* auth_with_context_fn)(context, + server, share, + workgroup, sizeof(workgroup), + username, sizeof(username), + password, sizeof(password)); + } + else + { + smbc_getFunctionAuthData(context)(server, share, + workgroup, sizeof(workgroup), + username, sizeof(username), + password, sizeof(password)); + } TALLOC_FREE(*pp_workgroup); TALLOC_FREE(*pp_username); -- cgit From 1335da2a7cc639310e5d389e8e8dbe67c4e7ca25 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Jul 2008 11:04:31 +0200 Subject: Refactoring: Change calling conventions for cli_rpc_pipe_open_noauth Pass in ndr_syntax_id instead of pipe_idx, return NTSTATUS (This used to be commit 9abc9dc4dc13bd3e42f98eff64eacf24b51f5779) --- source3/libsmb/libsmb_server.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source3/libsmb/libsmb_server.c') diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c index 7af5ca3a24..0a3287bc82 100644 --- a/source3/libsmb/libsmb_server.c +++ b/source3/libsmb/libsmb_server.c @@ -646,10 +646,9 @@ SMBC_attr_server(TALLOC_CTX *ctx, ZERO_STRUCTP(ipc_srv); ipc_srv->cli = ipc_cli; - pipe_hnd = cli_rpc_pipe_open_noauth(ipc_srv->cli, - PI_LSARPC, - &nt_status); - if (!pipe_hnd) { + nt_status = cli_rpc_pipe_open_noauth( + ipc_srv->cli, &ndr_table_lsarpc.syntax_id, &pipe_hnd); + if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(1, ("cli_nt_session_open fail!\n")); errno = ENOTSUP; cli_shutdown(ipc_srv->cli); -- cgit From 9c28ca2b6c967a2b2a073477d4d8070ce138b87e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 11 Sep 2008 18:45:26 +0200 Subject: fix nonempty blank lines (This used to be commit 3111428dd42abf856f646f2a3aa2ee78ff3d3702) --- source3/libsmb/libsmb_server.c | 196 ++++++++++++++++++++--------------------- 1 file changed, 98 insertions(+), 98 deletions(-) (limited to 'source3/libsmb/libsmb_server.c') diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c index 0a3287bc82..aeec255350 100644 --- a/source3/libsmb/libsmb_server.c +++ b/source3/libsmb/libsmb_server.c @@ -7,17 +7,17 @@ Copyright (C) Tom Jansen (Ninja ISD) 2002 Copyright (C) Derrell Lipman 2003-2008 Copyright (C) Jeremy Allison 2007, 2008 - + 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 the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see . */ @@ -40,7 +40,7 @@ SMBC_check_server(SMBCCTX * context, { socklen_t size; struct sockaddr addr; - + size = sizeof(addr); return (getpeername(server->cli->fd, &addr, &size) == -1); } @@ -56,12 +56,12 @@ SMBC_remove_unused_server(SMBCCTX * context, SMBCSRV * srv) { SMBCFILE * file; - + /* are we being fooled ? */ if (!context || !context->internal->initialized || !srv) { return 1; } - + /* Check all open files/directories for a relation with this server */ for (file = context->internal->files; file; file = file->next) { if (file->srv == srv) { @@ -72,16 +72,16 @@ SMBC_remove_unused_server(SMBCCTX * context, return 1; } } - + DLIST_REMOVE(context->internal->servers, srv); - + cli_shutdown(srv->cli); srv->cli = NULL; - + DEBUG(3, ("smbc_remove_usused_server: %p removed.\n", srv)); - + smbc_getFunctionRemoveCachedServer(context)(context, srv); - + SAFE_FREE(srv); return 0; } @@ -102,11 +102,11 @@ SMBC_call_auth_fn(TALLOC_CTX *ctx, fstring username; fstring password; smbc_get_auth_data_with_context_fn auth_with_context_fn; - + strlcpy(workgroup, *pp_workgroup, sizeof(workgroup)); strlcpy(username, *pp_username, sizeof(username)); strlcpy(password, *pp_password, sizeof(password)); - + /* See if there's an authentication with context function provided */ auth_with_context_fn = smbc_getFunctionAuthDataWithContext(context); if (auth_with_context_fn) @@ -124,11 +124,11 @@ SMBC_call_auth_fn(TALLOC_CTX *ctx, username, sizeof(username), password, sizeof(password)); } - + TALLOC_FREE(*pp_workgroup); TALLOC_FREE(*pp_username); TALLOC_FREE(*pp_password); - + *pp_workgroup = talloc_strdup(ctx, workgroup); *pp_username = talloc_strdup(ctx, username); *pp_password = talloc_strdup(ctx, password); @@ -157,23 +157,23 @@ SMBC_find_server(TALLOC_CTX *ctx, { SMBCSRV *srv; int auth_called = 0; - + if (!pp_workgroup || !pp_username || !pp_password) { return NULL; } - + check_server_cache: - + srv = smbc_getFunctionGetCachedServer(context)(context, server, share, *pp_workgroup, *pp_username); - + if (!auth_called && !srv && (!*pp_username || !(*pp_username)[0] || !*pp_password || !(*pp_password)[0])) { SMBC_call_auth_fn(ctx, context, server, share, pp_workgroup, pp_username, pp_password); - + /* * However, smbc_auth_fn may have picked up info relating to * an existing connection, so try for an existing connection @@ -181,9 +181,9 @@ check_server_cache: */ auth_called = 1; goto check_server_cache; - + } - + if (srv) { if (smbc_getFunctionCheckServer(context)(context, srv)) { /* @@ -202,17 +202,17 @@ check_server_cache: smbc_getFunctionRemoveCachedServer(context)(context, srv); } - + /* * Maybe there are more cached connections to this * server */ goto check_server_cache; } - + return srv; } - + return NULL; } @@ -247,19 +247,19 @@ SMBC_server(TALLOC_CTX *ctx, int port_try_next; const char *username_used; NTSTATUS status; - + zero_addr(&ss); ZERO_STRUCT(c); - + if (server[0] == 0) { errno = EPERM; return NULL; } - + /* Look for a cached connection */ srv = SMBC_find_server(ctx, context, server, share, pp_workgroup, pp_username, pp_password); - + /* * If we found a connection and we're only allowed one share per * server... @@ -267,7 +267,7 @@ SMBC_server(TALLOC_CTX *ctx, if (srv && *share != '\0' && smbc_getOptionOneSharePerServer(context)) { - + /* * ... then if there's no current connection to the share, * connect to it. SMBC_find_server(), or rather the function @@ -282,7 +282,7 @@ SMBC_server(TALLOC_CTX *ctx, pp_workgroup, pp_username, pp_password); - + if (!*pp_workgroup || !*pp_username || !*pp_password) { errno = ENOMEM; cli_shutdown(srv->cli); @@ -291,17 +291,17 @@ SMBC_server(TALLOC_CTX *ctx, srv); return NULL; } - + /* * We don't need to renegotiate encryption * here as the encryption context is not per * tid. */ - + if (!cli_send_tconX(srv->cli, share, "?????", *pp_password, strlen(*pp_password)+1)) { - + errno = SMBC_errno(context, srv->cli); cli_shutdown(srv->cli); srv->cli = NULL; @@ -309,7 +309,7 @@ SMBC_server(TALLOC_CTX *ctx, srv); srv = NULL; } - + /* * Regenerate the dev value since it's based on both * server and share @@ -320,42 +320,42 @@ SMBC_server(TALLOC_CTX *ctx, } } } - + /* If we have a connection... */ if (srv) { - + /* ... then we're done here. Give 'em what they came for. */ return srv; } - + /* If we're not asked to connect when a connection doesn't exist... */ if (! connect_if_not_found) { /* ... then we're done here. */ return NULL; } - + if (!*pp_workgroup || !*pp_username || !*pp_password) { errno = ENOMEM; return NULL; } - + make_nmb_name(&calling, smbc_getNetbiosName(context), 0x0); make_nmb_name(&called , server, 0x20); - + DEBUG(4,("SMBC_server: server_n=[%s] server=[%s]\n", server_n, server)); - + DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server)); - + again: - + zero_addr(&ss); - + /* have to open a new connection */ if ((c = cli_initialise()) == NULL) { errno = ENOMEM; return NULL; } - + if (smbc_getOptionUseKerberos(context)) { c->use_kerberos = True; } @@ -363,9 +363,9 @@ again: if (smbc_getOptionFallbackAfterKerberos(context)) { c->fallback_after_kerberos = True; } - + c->timeout = smbc_getTimeout(context); - + /* * Force use of port 139 for first try if share is $IPC, empty, or * null, so browse lists can work @@ -377,15 +377,15 @@ again: port_try_first = 445; port_try_next = 139; } - + c->port = port_try_first; - + status = cli_connect(c, server_n, &ss); if (!NT_STATUS_IS_OK(status)) { - + /* First connection attempt failed. Try alternate port. */ c->port = port_try_next; - + status = cli_connect(c, server_n, &ss); if (!NT_STATUS_IS_OK(status)) { cli_shutdown(c); @@ -393,20 +393,20 @@ again: return NULL; } } - + if (!cli_session_request(c, &calling, &called)) { cli_shutdown(c); if (strcmp(called.name, "*SMBSERVER")) { make_nmb_name(&called , "*SMBSERVER", 0x20); goto again; } else { /* Try one more time, but ensure we don't loop */ - + /* Only try this if server is an IP address ... */ - + if (is_ipaddress(server) && !tried_reverse) { fstring remote_name; struct sockaddr_storage rem_ss; - + if (!interpret_string_addr(&rem_ss, server, NI_NUMERICHOST)) { DEBUG(4, ("Could not convert IP address " @@ -415,9 +415,9 @@ again: errno = ETIMEDOUT; return NULL; } - + tried_reverse++; /* Yuck */ - + if (name_status_find("*", 0, 0, &rem_ss, remote_name)) { make_nmb_name(&called, @@ -430,65 +430,65 @@ again: errno = ETIMEDOUT; return NULL; } - + DEBUG(4,(" session request ok\n")); - + if (!cli_negprot(c)) { cli_shutdown(c); errno = ETIMEDOUT; return NULL; } - + username_used = *pp_username; - + if (!NT_STATUS_IS_OK(cli_session_setup(c, username_used, *pp_password, strlen(*pp_password), *pp_password, strlen(*pp_password), *pp_workgroup))) { - + /* Failed. Try an anonymous login, if allowed by flags. */ username_used = ""; - + if (smbc_getOptionNoAutoAnonymousLogin(context) || !NT_STATUS_IS_OK(cli_session_setup(c, username_used, *pp_password, 1, *pp_password, 0, *pp_workgroup))) { - + cli_shutdown(c); errno = EPERM; return NULL; } } - + DEBUG(4,(" session setup ok\n")); - + if (!cli_send_tconX(c, share, "?????", *pp_password, strlen(*pp_password)+1)) { errno = SMBC_errno(context, c); cli_shutdown(c); return NULL; } - + DEBUG(4,(" tconx ok\n")); - + if (context->internal->smb_encryption_level) { /* Attempt UNIX smb encryption. */ if (!NT_STATUS_IS_OK(cli_force_encryption(c, username_used, *pp_password, *pp_workgroup))) { - + /* * context->smb_encryption_level == 1 * means don't fail if encryption can't be negotiated, * == 2 means fail if encryption can't be negotiated. */ - + DEBUG(4,(" SMB encrypt failed\n")); - + if (context->internal->smb_encryption_level == 2) { cli_shutdown(c); errno = EPERM; @@ -497,25 +497,25 @@ again: } DEBUG(4,(" SMB encrypt ok\n")); } - + /* * Ok, we have got a nice connection * Let's allocate a server structure. */ - + srv = SMB_MALLOC_P(SMBCSRV); if (!srv) { errno = ENOMEM; goto failed; } - + ZERO_STRUCTP(srv); srv->cli = c; srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share)); srv->no_pathinfo = False; srv->no_pathinfo2 = 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; @@ -531,19 +531,19 @@ again: } goto failed; } - + DEBUG(2, ("Server connect ok: //%s/%s: %p\n", server, share, srv)); - + DLIST_ADD(context->internal->servers, srv); return srv; - + failed: cli_shutdown(c); if (!srv) { return NULL; } - + SAFE_FREE(srv); return NULL; } @@ -567,7 +567,7 @@ SMBC_attr_server(TALLOC_CTX *ctx, struct rpc_pipe_client *pipe_hnd; NTSTATUS nt_status; SMBCSRV *ipc_srv=NULL; - + /* * See if we've already created this special connection. Reference * our "special" share name '*IPC$', which is an impossible real share @@ -576,7 +576,7 @@ SMBC_attr_server(TALLOC_CTX *ctx, ipc_srv = SMBC_find_server(ctx, context, server, "*IPC$", pp_workgroup, pp_username, pp_password); if (!ipc_srv) { - + /* We didn't find a cached connection. Get the password */ if (!*pp_password || (*pp_password)[0] == '\0') { /* ... then retrieve it now. */ @@ -589,12 +589,12 @@ SMBC_attr_server(TALLOC_CTX *ctx, return NULL; } } - + flags = 0; if (smbc_getOptionUseKerberos(context)) { flags |= CLI_FULL_CONNECTION_USE_KERBEROS; } - + zero_addr(&ss); nt_status = cli_full_connection(&ipc_cli, global_myname(), server, @@ -610,23 +610,23 @@ SMBC_attr_server(TALLOC_CTX *ctx, errno = ENOTSUP; return NULL; } - + if (context->internal->smb_encryption_level) { /* Attempt UNIX smb encryption. */ if (!NT_STATUS_IS_OK(cli_force_encryption(ipc_cli, *pp_username, *pp_password, *pp_workgroup))) { - + /* * context->smb_encryption_level == * 1 means don't fail if encryption can't be * negotiated, == 2 means fail if encryption * can't be negotiated. */ - + DEBUG(4,(" SMB encrypt failed on IPC$\n")); - + if (context->internal->smb_encryption_level == 2) { cli_shutdown(ipc_cli); errno = EPERM; @@ -635,17 +635,17 @@ SMBC_attr_server(TALLOC_CTX *ctx, } DEBUG(4,(" SMB encrypt ok on IPC$\n")); } - + ipc_srv = SMB_MALLOC_P(SMBCSRV); if (!ipc_srv) { errno = ENOMEM; cli_shutdown(ipc_cli); return NULL; } - + ZERO_STRUCTP(ipc_srv); ipc_srv->cli = ipc_cli; - + nt_status = cli_rpc_pipe_open_noauth( ipc_srv->cli, &ndr_table_lsarpc.syntax_id, &pipe_hnd); if (!NT_STATUS_IS_OK(nt_status)) { @@ -655,28 +655,28 @@ SMBC_attr_server(TALLOC_CTX *ctx, free(ipc_srv); return NULL; } - + /* * Some systems don't support * SEC_RIGHTS_MAXIMUM_ALLOWED, but NT sends 0x2000000 * so we might as well do it too. */ - + nt_status = rpccli_lsa_open_policy( pipe_hnd, talloc_tos(), True, GENERIC_EXECUTE_ACCESS, &ipc_srv->pol); - + if (!NT_STATUS_IS_OK(nt_status)) { errno = SMBC_errno(context, ipc_srv->cli); cli_shutdown(ipc_srv->cli); return NULL; } - + /* now add it to the cache (internal or external) */ - + errno = 0; /* let cache function set errno if it likes */ if (smbc_getFunctionAddCachedServer(context)(context, ipc_srv, server, @@ -691,9 +691,9 @@ SMBC_attr_server(TALLOC_CTX *ctx, free(ipc_srv); return NULL; } - + DLIST_ADD(context->internal->servers, ipc_srv); } - + return ipc_srv; } -- cgit