From d06559c1e6ac0d9a9092e21c703397eb588aef94 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 16 Jan 2008 15:52:53 +0100 Subject: Make resolve_ads() static. Guenther (This used to be commit 57dc747136e880a25c03bdc4a1431fc41afd93a1) --- source3/libsmb/namequery.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c index ad999b34b4..ad16452e3e 100644 --- a/source3/libsmb/namequery.c +++ b/source3/libsmb/namequery.c @@ -1299,11 +1299,11 @@ static NTSTATUS resolve_hosts(const char *name, int name_type, Resolve via "ADS" method. *********************************************************/ -NTSTATUS resolve_ads(const char *name, - int name_type, - const char *sitename, - struct ip_service **return_iplist, - int *return_count) +static NTSTATUS resolve_ads(const char *name, + int name_type, + const char *sitename, + struct ip_service **return_iplist, + int *return_count) { int i, j; NTSTATUS status; -- cgit From f44713df4d636203354c55d9a9bc2538073cf0af Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 16 Jan 2008 17:33:19 -0800 Subject: Fix bug found by Derrell - windows returns an read return offset of zero if return size is zero. Should fix testread libsmbclient code. Jeremy. (This used to be commit df3c4648399f8d62ff6fe0013be8b89abc18f0f0) --- source3/libsmb/clireadwrite.c | 49 ++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 21 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 6b39a885f0..af13ed8f73 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -134,6 +134,8 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ return -1; } + /* size2 is the number of bytes the server returned. + * Might be zero. */ size2 = SVAL(cli->inbuf, smb_vwv5); size2 |= (((unsigned int)(SVAL(cli->inbuf, smb_vwv7))) << 16); @@ -145,27 +147,32 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_ return -1; } - if (!direct_reads) { - /* Copy data into buffer */ - p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6); - memcpy(buf + total, p, size2); - } else { - /* Ensure the remaining data matches the return size. */ - ssize_t toread = smb_len_large(cli->inbuf) - SVAL(cli->inbuf,smb_vwv6); - - /* Ensure the size is correct. */ - if (toread != size2) { - DEBUG(5,("direct read logic fail toread (%d) != size2 (%u)\n", - (int)toread, (unsigned int)size2 )); - return -1; - } - - /* Read data directly into buffer */ - toread = cli_receive_smb_data(cli,buf+total,size2); - if (toread != size2) { - DEBUG(5,("direct read read failure toread (%d) != size2 (%u)\n", - (int)toread, (unsigned int)size2 )); - return -1; + if (size2) { + /* smb_vwv6 is the offset in the packet of the returned + * data bytes. Only valid if size2 != 0. */ + + if (!direct_reads) { + /* Copy data into buffer */ + p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6); + memcpy(buf + total, p, size2); + } else { + /* Ensure the remaining data matches the return size. */ + ssize_t toread = smb_len_large(cli->inbuf) - SVAL(cli->inbuf,smb_vwv6); + + /* Ensure the size is correct. */ + if (toread != size2) { + DEBUG(5,("direct read logic fail toread (%d) != size2 (%u)\n", + (int)toread, (unsigned int)size2 )); + return -1; + } + + /* Read data directly into buffer */ + toread = cli_receive_smb_data(cli,buf+total,size2); + if (toread != size2) { + DEBUG(5,("direct read read failure toread (%d) != size2 (%u)\n", + (int)toread, (unsigned int)size2 )); + return -1; + } } } -- cgit From 096e40c9169b2121a82c42d3cf31cbfb869603ce Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Thu, 17 Jan 2008 09:29:13 -0500 Subject: Fix stat results to be consistent between smbc_stat and smbc_fstat. We create a kludged inode based on the checksum of the path. We therefore need to use the same (full) path when calculating it in both smbc_stat() and smbc_fstat(). If struct stat has an rdev field, set it to zero. Derrell (This used to be commit b4282fbd6d27d868b2d5c04bb72d2d7421822da1) --- source3/libsmb/libsmbclient.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c index fb04d143a5..077970647d 100644 --- a/source3/libsmb/libsmbclient.c +++ b/source3/libsmb/libsmbclient.c @@ -2263,6 +2263,9 @@ smbc_setup_stat(SMBCCTX *context, #endif #ifdef HAVE_STAT_ST_BLOCKS st->st_blocks = (size+511)/512; +#endif +#ifdef HAVE_STRUCT_STAT_ST_RDEV + st->st_rdev = 0; #endif st->st_uid = getuid(); st->st_gid = getgid(); @@ -2367,7 +2370,7 @@ smbc_stat_ctx(SMBCCTX *context, st->st_ino = ino; - smbc_setup_stat(context, st, path, size, mode); + smbc_setup_stat(context, st, (char *) fname, size, mode); set_atimespec(st, access_time_ts); set_ctimespec(st, change_time_ts); -- cgit From 4f09727df8502c3a66cbf0cb423da1067d215c90 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Thu, 17 Jan 2008 11:49:17 -0500 Subject: Fix bug 5185: repeated calls to smbc_getxattr() lose sid-name mapping If we're going to cache connections to IPC$, we'd better also cache the policy handle and not use a stack-based handle that's invalid on subsequent calls. Derrell (This used to be commit 67c415661f6466c21cd0eaafabe58cba049d2af3) --- source3/libsmb/libsmbclient.c | 83 +++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 46 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c index 077970647d..2fd8294d04 100644 --- a/source3/libsmb/libsmbclient.c +++ b/source3/libsmb/libsmbclient.c @@ -1037,8 +1037,7 @@ smbc_attr_server(TALLOC_CTX *ctx, const char *share, char **pp_workgroup, char **pp_username, - char **pp_password, - POLICY_HND *pol) + char **pp_password) { int flags; struct sockaddr_storage ss; @@ -1122,36 +1121,34 @@ smbc_attr_server(TALLOC_CTX *ctx, ZERO_STRUCTP(ipc_srv); ipc_srv->cli = ipc_cli; - if (pol) { - 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. - */ + 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; + } - nt_status = rpccli_lsa_open_policy( - pipe_hnd, - talloc_tos(), - True, - GENERIC_EXECUTE_ACCESS, - pol); + /* + * Some systems don't support + * SEC_RIGHTS_MAXIMUM_ALLOWED, but NT sends 0x2000000 + * so we might as well do it too. + */ - if (!NT_STATUS_IS_OK(nt_status)) { - errno = smbc_errno(context, ipc_srv->cli); - cli_shutdown(ipc_srv->cli); - return NULL; - } + 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) */ @@ -5728,7 +5725,6 @@ smbc_setxattr_ctx(SMBCCTX *context, char *password = NULL; char *workgroup = NULL; char *path = NULL; - POLICY_HND pol; DOS_ATTR_DESC *dad = NULL; struct { const char * create_time_attr; @@ -5787,8 +5783,7 @@ smbc_setxattr_ctx(SMBCCTX *context, if (! srv->no_nt_session) { ipc_srv = smbc_attr_server(frame, context, server, share, - &workgroup, &user, &password, - &pol); + &workgroup, &user, &password); if (! ipc_srv) { srv->no_nt_session = True; } @@ -5814,7 +5809,7 @@ smbc_setxattr_ctx(SMBCCTX *context, if (ipc_srv) { ret = cacl_set(talloc_tos(), srv->cli, - ipc_srv->cli, &pol, path, + ipc_srv->cli, &ipc_srv->pol, path, namevalue, (*namevalue == '*' ? SMBC_XATTR_MODE_SET @@ -5878,7 +5873,7 @@ smbc_setxattr_ctx(SMBCCTX *context, ret = -1; } else { ret = cacl_set(talloc_tos(), srv->cli, - ipc_srv->cli, &pol, path, + ipc_srv->cli, &ipc_srv->pol, path, namevalue, (*namevalue == '*' ? SMBC_XATTR_MODE_SET @@ -5908,7 +5903,7 @@ smbc_setxattr_ctx(SMBCCTX *context, ret = -1; } else { ret = cacl_set(talloc_tos(), srv->cli, - ipc_srv->cli, &pol, path, + ipc_srv->cli, &ipc_srv->pol, path, namevalue, SMBC_XATTR_MODE_CHOWN, 0); } TALLOC_FREE(frame); @@ -5935,7 +5930,7 @@ smbc_setxattr_ctx(SMBCCTX *context, ret = -1; } else { ret = cacl_set(talloc_tos(), srv->cli, - ipc_srv->cli, &pol, path, + ipc_srv->cli, &ipc_srv->pol, path, namevalue, SMBC_XATTR_MODE_CHOWN, 0); } TALLOC_FREE(frame); @@ -6026,7 +6021,6 @@ smbc_getxattr_ctx(SMBCCTX *context, char *password = NULL; char *workgroup = NULL; char *path = NULL; - POLICY_HND pol; struct { const char * create_time_attr; const char * access_time_attr; @@ -6083,8 +6077,7 @@ smbc_getxattr_ctx(SMBCCTX *context, if (! srv->no_nt_session) { ipc_srv = smbc_attr_server(frame, context, server, share, - &workgroup, &user, &password, - &pol); + &workgroup, &user, &password); if (! ipc_srv) { srv->no_nt_session = True; } @@ -6137,7 +6130,7 @@ smbc_getxattr_ctx(SMBCCTX *context, /* Yup. */ ret = cacl_get(context, talloc_tos(), srv, ipc_srv == NULL ? NULL : ipc_srv->cli, - &pol, path, + &ipc_srv->pol, path, CONST_DISCARD(char *, name), CONST_DISCARD(char *, value), size); if (ret < 0 && errno == 0) { @@ -6168,7 +6161,6 @@ smbc_removexattr_ctx(SMBCCTX *context, char *password = NULL; char *workgroup = NULL; char *path = NULL; - POLICY_HND pol; TALLOC_CTX *frame = talloc_stackframe(); if (!context || !context->internal || @@ -6219,8 +6211,7 @@ smbc_removexattr_ctx(SMBCCTX *context, if (! srv->no_nt_session) { ipc_srv = smbc_attr_server(frame, context, server, share, - &workgroup, &user, &password, - &pol); + &workgroup, &user, &password); if (! ipc_srv) { srv->no_nt_session = True; } @@ -6239,7 +6230,7 @@ smbc_removexattr_ctx(SMBCCTX *context, /* Yup. */ ret = cacl_set(talloc_tos(), srv->cli, - ipc_srv->cli, &pol, path, + ipc_srv->cli, &ipc_srv->pol, path, NULL, SMBC_XATTR_MODE_REMOVE_ALL, 0); TALLOC_FREE(frame); return ret; @@ -6259,7 +6250,7 @@ smbc_removexattr_ctx(SMBCCTX *context, /* Yup. */ ret = cacl_set(talloc_tos(), srv->cli, - ipc_srv->cli, &pol, path, + ipc_srv->cli, &ipc_srv->pol, path, name + 19, SMBC_XATTR_MODE_REMOVE, 0); TALLOC_FREE(frame); return ret; -- cgit From 80d7cccfe7d6179da75c00481f2116dae6755682 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 18 Jan 2008 01:04:40 +0100 Subject: Add and correct some WERROR codes. Michael (This used to be commit 7aec862ddc2aa2b5152c3a452971e55ba43646a5) --- source3/libsmb/doserr.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/doserr.c b/source3/libsmb/doserr.c index 79445a2410..174db312c8 100644 --- a/source3/libsmb/doserr.c +++ b/source3/libsmb/doserr.c @@ -74,7 +74,7 @@ werror_code_struct dos_errs[] = { "WERR_DFS_INTERNAL_ERROR", WERR_DFS_INTERNAL_ERROR }, { "WERR_DFS_CANT_CREATE_JUNCT", WERR_DFS_CANT_CREATE_JUNCT }, { "WERR_MACHINE_LOCKED", WERR_MACHINE_LOCKED }, - { "WERR_DOMAIN_CONTROLLER_NOT_FOUND", WERR_DOMAIN_CONTROLLER_NOT_FOUND }, + { "WERR_DC_NOT_FOUND", WERR_DC_NOT_FOUND }, { "WERR_SETUP_NOT_JOINED", WERR_SETUP_NOT_JOINED }, { "WERR_SETUP_ALREADY_JOINED", WERR_SETUP_ALREADY_JOINED }, { "WERR_SETUP_DOMAIN_CONTROLLER", WERR_SETUP_DOMAIN_CONTROLLER }, @@ -96,6 +96,9 @@ werror_code_struct dos_errs[] = { "WERR_SERVICE_DISABLED", WERR_SERVICE_DISABLED }, { "WERR_CAN_NOT_COMPLETE", WERR_CAN_NOT_COMPLETE}, { "WERR_INVALID_FLAGS", WERR_INVALID_FLAGS}, + { "WERR_PASSWORD_MUST_CHANGE", WERR_PASSWORD_MUST_CHANGE }, + { "WERR_DOMAIN_CONTROLLER_NOT_FOUND", WERR_DOMAIN_CONTROLLER_NOT_FOUND }, + { "WERR_ACCOUNT_LOCKED_OUT", WERR_ACCOUNT_LOCKED_OUT }, { NULL, W_ERROR(0) } }; @@ -109,11 +112,14 @@ werror_str_struct dos_err_strs[] = { { WERR_NO_LOGON_SERVERS, "No logon servers found" }, { WERR_NO_SUCH_LOGON_SESSION, "No such logon session" }, { WERR_DOMAIN_CONTROLLER_NOT_FOUND, "A domain controller could not be found" }, + { WERR_DC_NOT_FOUND, "A domain controller could not be found" }, { WERR_SETUP_NOT_JOINED, "Join failed" }, { WERR_SETUP_ALREADY_JOINED, "Machine is already joined" }, { WERR_SETUP_DOMAIN_CONTROLLER, "Machine is a Domain Controller" }, { WERR_LOGON_FAILURE, "Invalid logon credentials" }, { WERR_USER_EXISTS, "User account already exists" }, + { WERR_PASSWORD_MUST_CHANGE, "The password must be changed" }, + { WERR_ACCOUNT_LOCKED_OUT, "Account locked out" }, }; /***************************************************************************** -- cgit From 3d3d6e7020749c63455e16ba110bc46862d3c146 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 18 Jan 2008 11:08:17 +0100 Subject: Add the "allinfo" command to smbclient Modeled after the Samba4 allinfo command (This used to be commit 3fa0cf3fe5f819f6e76df6f7cef3bb4e1c307a52) --- source3/libsmb/clirap.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c index aab77a3d54..4c5e338606 100644 --- a/source3/libsmb/clirap.c +++ b/source3/libsmb/clirap.c @@ -805,6 +805,137 @@ bool cli_qpathinfo2(struct cli_state *cli, const char *fname, return True; } +/**************************************************************************** + Get the stream info +****************************************************************************/ + +bool cli_qpathinfo_streams(struct cli_state *cli, const char *fname, + TALLOC_CTX *mem_ctx, + unsigned int *pnum_streams, + struct stream_struct **pstreams) +{ + unsigned int data_len = 0; + unsigned int param_len = 0; + uint16 setup = TRANSACT2_QPATHINFO; + char *param; + char *rparam=NULL, *rdata=NULL; + char *p; + unsigned int num_streams; + struct stream_struct *streams; + unsigned int ofs; + size_t namelen = 2*(strlen(fname)+1); + + param = SMB_MALLOC_ARRAY(char, 6+namelen+2); + if (param == NULL) { + return false; + } + p = param; + memset(p, 0, 6); + SSVAL(p, 0, SMB_FILE_STREAM_INFORMATION); + p += 6; + p += clistr_push(cli, p, fname, namelen, STR_TERMINATE); + + param_len = PTR_DIFF(p, param); + + if (!cli_send_trans(cli, SMBtrans2, + NULL, /* name */ + -1, 0, /* fid, flags */ + &setup, 1, 0, /* setup, len, max */ + param, param_len, 10, /* param, len, max */ + NULL, data_len, cli->max_xmit /* data, len, max */ + )) { + return false; + } + + if (!cli_receive_trans(cli, SMBtrans2, + &rparam, ¶m_len, + &rdata, &data_len)) { + return false; + } + + if (!rdata) { + SAFE_FREE(rparam); + return false; + } + + num_streams = 0; + streams = NULL; + ofs = 0; + + while ((data_len > ofs) && (data_len - ofs >= 24)) { + uint32_t nlen, len; + ssize_t size; + void *vstr; + struct stream_struct *tmp; + uint8_t *tmp_buf; + + tmp = TALLOC_REALLOC_ARRAY(mem_ctx, streams, + struct stream_struct, + num_streams+1); + + if (tmp == NULL) { + goto fail; + } + streams = tmp; + + nlen = IVAL(rdata, ofs + 0x04); + + streams[num_streams].size = IVAL_TO_SMB_OFF_T( + rdata, ofs + 0x08); + streams[num_streams].alloc_size = IVAL_TO_SMB_OFF_T( + rdata, ofs + 0x10); + + if (nlen > data_len - (ofs + 24)) { + goto fail; + } + + /* + * We need to null-terminate src, how do I do this with + * convert_string_talloc?? + */ + + tmp_buf = TALLOC_ARRAY(streams, uint8_t, nlen+2); + if (tmp_buf == NULL) { + goto fail; + } + + memcpy(tmp_buf, rdata+ofs+24, nlen); + tmp_buf[nlen] = 0; + tmp_buf[nlen+1] = 0; + + size = convert_string_talloc(streams, CH_UTF16, CH_UNIX, + tmp_buf, nlen+2, &vstr, + false); + TALLOC_FREE(tmp_buf); + + if (size == -1) { + goto fail; + } + streams[num_streams].name = (char *)vstr; + num_streams++; + + len = IVAL(rdata, ofs); + if (len > data_len - ofs) { + goto fail; + } + if (len == 0) break; + ofs += len; + } + + SAFE_FREE(rdata); + SAFE_FREE(rparam); + + *pnum_streams = num_streams; + *pstreams = streams; + return true; + + fail: + TALLOC_FREE(streams); + SAFE_FREE(rdata); + SAFE_FREE(rparam); + return false; +} + /**************************************************************************** Send a qfileinfo QUERY_FILE_NAME_INFO call. ****************************************************************************/ -- cgit From bb707b1db6add166a7887284281fa4b65776be08 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Fri, 18 Jan 2008 14:22:49 -0500 Subject: Fix typo that disabled setting group id. Thanks, Henrik. (This used to be commit 843e1694cfe4a999ed14a9c215b8e77723d0fe79) --- source3/libsmb/libsmbclient.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c index 2fd8294d04..fbcb7f64e2 100644 --- a/source3/libsmb/libsmbclient.c +++ b/source3/libsmb/libsmbclient.c @@ -5931,7 +5931,7 @@ smbc_setxattr_ctx(SMBCCTX *context, } else { ret = cacl_set(talloc_tos(), srv->cli, ipc_srv->cli, &ipc_srv->pol, path, - namevalue, SMBC_XATTR_MODE_CHOWN, 0); + namevalue, SMBC_XATTR_MODE_CHGRP, 0); } TALLOC_FREE(frame); return ret; -- cgit From a925a53f61ebdc6b4386b7c0853f2f87cbe2e166 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 23 Jan 2008 16:42:31 +0100 Subject: read_socket_with_timeout has timeout=0 handling (This used to be commit 7101026061c470ed962267b43ac0aa67cc761a64) --- source3/libsmb/clientgen.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index ecef293d07..042b3bdfb0 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -180,12 +180,8 @@ bool cli_receive_smb(struct cli_state *cli) ssize_t cli_receive_smb_data(struct cli_state *cli, char *buffer, size_t len) { - if (cli->timeout > 0) { - return read_socket_with_timeout(cli->fd, buffer, len, - len, cli->timeout, &cli->smb_rw_error); - } else { - return read_data(cli->fd, buffer, len, &cli->smb_rw_error); - } + return read_socket_with_timeout(cli->fd, buffer, len, len, + cli->timeout, &cli->smb_rw_error); } /**************************************************************************** -- cgit From 691c4b1a4175e3d4a073c396a2a7d8d315cd42bd Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 17 Jan 2008 10:11:11 +0100 Subject: Windows 2008 (Longhorn) auth2 flag fixes. Interop fixes for AD specific flags. Original patch from Todd Stetcher. (This used to be commit 5aadfcdaacd6f136eab9e107a88b8544e6d2105f) --- source3/libsmb/trusts_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c index 732dc78c75..1ca7d56a83 100644 --- a/source3/libsmb/trusts_util.c +++ b/source3/libsmb/trusts_util.c @@ -40,7 +40,7 @@ static NTSTATUS just_change_the_password(struct rpc_pipe_client *cli, TALLOC_CTX already have valid creds. If not we must set them up. */ if (cli->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) { - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; + uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS; result = rpccli_netlogon_setup_creds(cli, cli->cli->desthost, /* server name */ -- cgit From cfe7b54e96d39d19ad6b28c0d7db380907171e21 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 17 Jan 2008 11:35:40 +0100 Subject: Fix Windows 2008 (Longhorn) join. During 'net ads join' the cli->desthost is a hostname (e.g. rupert.galaxy.site). Check if we have a hostname and use only the first part, the machine name, of the string. (This used to be commit 5f60ed4af680ba2811db8d9f8267348ce05f26d2) --- source3/libsmb/cliconnect.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 4560521d4a..de5813df6b 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -872,13 +872,26 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, !strequal(star_smbserver_name, cli->desthost)) { char *realm = NULL; + char *machine = NULL; + char *host = NULL; DEBUG(3,("cli_session_setup_spnego: got a " "bad server principal, trying to guess ...\n")); + host = strchr(cli->desthost, '.'); + if (host) { + machine = SMB_STRNDUP(cli->desthost, + host - cli->desthost); + } else { + machine = SMB_STRDUP(cli->desthost); + } + if (machine == NULL) { + return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); + } + realm = kerberos_get_default_realm_from_ccache(); if (realm && *realm) { if (asprintf(&principal, "%s$@%s", - cli->desthost, realm) < 0) { + machine, realm) < 0) { SAFE_FREE(realm); return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); } @@ -886,6 +899,7 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, "server principal=%s\n", principal ? principal : "")); } + SAFE_FREE(machine); SAFE_FREE(realm); } -- cgit From fe8a8f47e0eefd064031e87fec4cdd2736716550 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 23 Jan 2008 15:00:40 -0800 Subject: Use strchr_m in seaching for '.' in the hostname to make sure we're mb safe. Jeremy. (This used to be commit 090061b73a1c086ff8a7797e1a63532eacd91148) --- source3/libsmb/cliconnect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index de5813df6b..fd860ae7f0 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -877,7 +877,7 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, DEBUG(3,("cli_session_setup_spnego: got a " "bad server principal, trying to guess ...\n")); - host = strchr(cli->desthost, '.'); + host = strchr_m(cli->desthost, '.'); if (host) { machine = SMB_STRNDUP(cli->desthost, host - cli->desthost); -- cgit From ffc84a10447a1bd3329b874b9e1bd4c6e6c2ff66 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 23 Jan 2008 15:23:16 -0800 Subject: Don't leak memory in error path. Jeremy. (This used to be commit 2df0cdaafdced798f81e30d34371aa1d8e963208) --- source3/libsmb/cliconnect.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/libsmb') diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index fd860ae7f0..f3926b777b 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -892,6 +892,7 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, if (realm && *realm) { if (asprintf(&principal, "%s$@%s", machine, realm) < 0) { + SAFE_FREE(machine); SAFE_FREE(realm); return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); } -- cgit From e0021b586d0c882fcc5ce0566dbbbd76f163d170 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Wed, 23 Jan 2008 20:44:54 -0500 Subject: Allow clearing all settable DOS mode bits. A mode value of zero is ignored by Windows. If the requested mode is zero, we instead send the appropriate one of 0x80 (NORMAL) or 0x10 (DIRECTORY). Thanks Jeremy! Derrell (This used to be commit 54abf7d0e595e9cbeea115a40d4f7b995252a150) --- source3/libsmb/libsmbclient.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c index fbcb7f64e2..2eb580a52d 100644 --- a/source3/libsmb/libsmbclient.c +++ b/source3/libsmb/libsmbclient.c @@ -4689,7 +4689,15 @@ dos_attr_parse(SMBCCTX *context, frame = talloc_stackframe(); while (next_token_talloc(frame, &p, &tok, "\t,\r\n")) { if (StrnCaseCmp(tok, "MODE:", 5) == 0) { - dad->mode = strtol(tok+5, NULL, 16); + long request = strtol(tok+5, NULL, 16); + if (request == 0) { + dad->mode = (request | + (IS_DOS_DIR(dad->mode) + ? FILE_ATTRIBUTE_DIRECTORY + : FILE_ATTRIBUTE_NORMAL)); + } else { + dad->mode = request; + } continue; } -- cgit From 372f74bba2650cb4f4c8f262c6cf8d761a753e81 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 24 Jan 2008 23:39:38 +0100 Subject: Add WERR_INVALID_COMPUTER_NAME. Guenther (This used to be commit cb1ff32eff06031150a6821658152e02a4077bbd) --- source3/libsmb/doserr.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/libsmb') diff --git a/source3/libsmb/doserr.c b/source3/libsmb/doserr.c index 174db312c8..a3043a2152 100644 --- a/source3/libsmb/doserr.c +++ b/source3/libsmb/doserr.c @@ -73,6 +73,7 @@ werror_code_struct dos_errs[] = { "WERR_DFS_NO_SUCH_SERVER", WERR_DFS_NO_SUCH_SERVER }, { "WERR_DFS_INTERNAL_ERROR", WERR_DFS_INTERNAL_ERROR }, { "WERR_DFS_CANT_CREATE_JUNCT", WERR_DFS_CANT_CREATE_JUNCT }, + { "WERR_INVALID_COMPUTER_NAME", WERR_INVALID_COMPUTER_NAME }, { "WERR_MACHINE_LOCKED", WERR_MACHINE_LOCKED }, { "WERR_DC_NOT_FOUND", WERR_DC_NOT_FOUND }, { "WERR_SETUP_NOT_JOINED", WERR_SETUP_NOT_JOINED }, -- cgit From 54db1839878641be1a9987ad3e0ddedbd6123b7c Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 27 Jan 2008 17:31:56 +1100 Subject: Adding missing calls to va_end(). Just a small commit to get a handle on this git thingy. This patch fixes some missing calls to va_end() to match various calls to va_start() and VA_COPY(). Tim. (This used to be commit ec367f307dff7948722b9ac97beb960efd91991f) --- source3/libsmb/ntlmssp_parse.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/ntlmssp_parse.c b/source3/libsmb/ntlmssp_parse.c index ac8846ad1e..70377cba7d 100644 --- a/source3/libsmb/ntlmssp_parse.c +++ b/source3/libsmb/ntlmssp_parse.c @@ -170,6 +170,7 @@ bool msrpc_gen(DATA_BLOB *blob, /* a helpful macro to avoid running over the end of our blob */ #define NEED_DATA(amount) \ if ((head_ofs + amount) > blob->length) { \ + va_end(ap); \ return False; \ } @@ -216,16 +217,20 @@ bool msrpc_parse(const DATA_BLOB *blob, if ((len1 != len2) || (ptr + len1 < ptr) || (ptr + len1 < len1) || (ptr + len1 > blob->length)) { + va_end(ap); return false; } if (len1 & 1) { /* if odd length and unicode */ + va_end(ap); return false; } if (blob->data + ptr < (uint8 *)(unsigned long)ptr || - blob->data + ptr < blob->data) + blob->data + ptr < blob->data) { + va_end(ap); return false; + } if (0 < len1) { char *p = NULL; @@ -261,13 +266,16 @@ bool msrpc_parse(const DATA_BLOB *blob, if ((len1 != len2) || (ptr + len1 < ptr) || (ptr + len1 < len1) || (ptr + len1 > blob->length)) { + va_end(ap); return false; } if (blob->data + ptr < (uint8 *)(unsigned long)ptr || - blob->data + ptr < blob->data) + blob->data + ptr < blob->data) { + va_end(ap); return false; + } if (0 < len1) { char *p = NULL; @@ -304,13 +312,16 @@ bool msrpc_parse(const DATA_BLOB *blob, if ((len1 != len2) || (ptr + len1 < ptr) || (ptr + len1 < len1) || (ptr + len1 > blob->length)) { + va_end(ap); return false; } if (blob->data + ptr < (uint8 *)(unsigned long)ptr || - blob->data + ptr < blob->data) + blob->data + ptr < blob->data) { + va_end(ap); return false; + } *b = data_blob(blob->data + ptr, len1); } @@ -322,6 +333,7 @@ bool msrpc_parse(const DATA_BLOB *blob, NEED_DATA(len1); if (blob->data + head_ofs < (uint8 *)head_ofs || blob->data + head_ofs < blob->data) { + va_end(ap); return false; } @@ -337,7 +349,8 @@ bool msrpc_parse(const DATA_BLOB *blob, s = va_arg(ap, char *); if (blob->data + head_ofs < (uint8 *)head_ofs || - blob->data + head_ofs < blob->data) { + blob->data + head_ofs < blob->data) { + va_end(ap); return false; } @@ -351,11 +364,13 @@ bool msrpc_parse(const DATA_BLOB *blob, blob->length - head_ofs, STR_ASCII|STR_TERMINATE); if (ret == (size_t)-1 || p == NULL) { + va_end(ap); return false; } head_ofs += ret; if (strcmp(s, p) != 0) { TALLOC_FREE(p); + va_end(ap); return false; } TALLOC_FREE(p); -- cgit From 5ab43ae0d8e66a1fd4c877089df52282367be7dd Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sat, 26 Jan 2008 01:39:33 +0100 Subject: Eliminate remote tree of dsgetdcname (which will happen in libnetapi then). Guenther (This used to be commit fd490d236b1fb73a75c457b75128c9b98719418f) --- source3/libsmb/dsgetdcname.c | 114 ++++++------------------------------------- 1 file changed, 14 insertions(+), 100 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c index 2a66d51400..e0be76cc85 100644 --- a/source3/libsmb/dsgetdcname.c +++ b/source3/libsmb/dsgetdcname.c @@ -891,72 +891,27 @@ static NTSTATUS dsgetdcname_rediscover(TALLOC_CTX *mem_ctx, } /******************************************************************** -********************************************************************/ - -NTSTATUS dsgetdcname_remote(TALLOC_CTX *mem_ctx, - const char *computer_name, - const char *domain_name, - struct GUID *domain_guid, - const char *site_name, - uint32_t flags, - struct DS_DOMAIN_CONTROLLER_INFO **info) -{ - WERROR werr; - NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; - struct cli_state *cli = NULL; - struct rpc_pipe_client *pipe_cli = NULL; - - status = cli_full_connection(&cli, NULL, computer_name, - NULL, 0, - "IPC$", "IPC", - "", - "", - "", - 0, Undefined, NULL); - - if (!NT_STATUS_IS_OK(status)) { - goto done; - } - - pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, - &status); - if (!pipe_cli) { - goto done; - } - - werr = rpccli_netlogon_dsr_getdcname(pipe_cli, - mem_ctx, - computer_name, - domain_name, - domain_guid, - NULL, - flags, - info); - status = werror_to_ntstatus(werr); - - done: - cli_rpc_pipe_close(pipe_cli); - if (cli) { - cli_shutdown(cli); - } - - return status; -} + dsgetdcname. -/******************************************************************** + This will be the only public function here. ********************************************************************/ -NTSTATUS dsgetdcname_local(TALLOC_CTX *mem_ctx, - const char *computer_name, - const char *domain_name, - struct GUID *domain_guid, - const char *site_name, - uint32_t flags, - struct DS_DOMAIN_CONTROLLER_INFO **info) +NTSTATUS dsgetdcname(TALLOC_CTX *mem_ctx, + const char *domain_name, + struct GUID *domain_guid, + const char *site_name, + uint32_t flags, + struct DS_DOMAIN_CONTROLLER_INFO **info) { NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; struct DS_DOMAIN_CONTROLLER_INFO *myinfo = NULL; + DEBUG(10,("dsgetdcname: domain_name: %s, " + "domain_guid: %s, site_name: %s, flags: 0x%08x\n", + domain_name, + domain_guid ? GUID_string(mem_ctx, domain_guid) : "(null)", + site_name, flags)); + *info = NULL; if (!check_allowed_required_flags(flags)) { @@ -991,44 +946,3 @@ NTSTATUS dsgetdcname_local(TALLOC_CTX *mem_ctx, return status; } - -/******************************************************************** - dsgetdcname. - - This will be the only public function here. -********************************************************************/ - -NTSTATUS dsgetdcname(TALLOC_CTX *mem_ctx, - const char *computer_name, - const char *domain_name, - struct GUID *domain_guid, - const char *site_name, - uint32_t flags, - struct DS_DOMAIN_CONTROLLER_INFO **info) -{ - DEBUG(10,("dsgetdcname: computer_name: %s, domain_name: %s, " - "domain_guid: %s, site_name: %s, flags: 0x%08x\n", - computer_name, domain_name, - domain_guid ? GUID_string(mem_ctx, domain_guid) : "(null)", - site_name, flags)); - - *info = NULL; - - if (computer_name) { - return dsgetdcname_remote(mem_ctx, - computer_name, - domain_name, - domain_guid, - site_name, - flags, - info); - } - - return dsgetdcname_local(mem_ctx, - computer_name, - domain_name, - domain_guid, - site_name, - flags, - info); -} -- cgit From 5e43eeb1b6eef7ea7a88ffc51a0a0535e9bd8023 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 25 Jan 2008 23:41:48 +0100 Subject: Get rid of read_socket_with_timeout (This used to be commit f9c8ac83ff42137d2101d3bb17e5dcc3c3d70a8f) --- source3/libsmb/clientgen.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 042b3bdfb0..086c158ed2 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -180,8 +180,28 @@ bool cli_receive_smb(struct cli_state *cli) ssize_t cli_receive_smb_data(struct cli_state *cli, char *buffer, size_t len) { - return read_socket_with_timeout(cli->fd, buffer, len, len, - cli->timeout, &cli->smb_rw_error); + NTSTATUS status; + + set_smb_read_error(&cli->smb_rw_error, SMB_READ_OK); + + status = read_socket_with_timeout_ntstatus( + cli->fd, buffer, len, len, cli->timeout, NULL); + if (NT_STATUS_IS_OK(status)) { + return len; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { + set_smb_read_error(&cli->smb_rw_error, SMB_READ_EOF); + return -1; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { + set_smb_read_error(&cli->smb_rw_error, SMB_READ_TIMEOUT); + return -1; + } + + set_smb_read_error(&cli->smb_rw_error, SMB_READ_ERROR); + return -1; } /**************************************************************************** -- cgit From 6ddfa6ae7734ffdd26ac38478c27cc9d646ddadd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 25 Jan 2008 23:43:50 +0100 Subject: read_socket_with_timeout_ntstatus->read_socket_with_timeout (This used to be commit 90554799afa42855c3e7b87dc632e67f0952f988) --- source3/libsmb/clientgen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 086c158ed2..7a7377f148 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -184,7 +184,7 @@ ssize_t cli_receive_smb_data(struct cli_state *cli, char *buffer, size_t len) set_smb_read_error(&cli->smb_rw_error, SMB_READ_OK); - status = read_socket_with_timeout_ntstatus( + status = read_socket_with_timeout( cli->fd, buffer, len, len, cli->timeout, NULL); if (NT_STATUS_IS_OK(status)) { return len; -- cgit From 88c27f83d449fa20cba47cbf0a5dbaedc99859d8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 25 Jan 2008 23:54:22 +0100 Subject: Convert receive_smb_raw to NTSTATUS (This used to be commit ba771bd858602452a9e58c3aab1336f2ac8a25ef) --- source3/libsmb/clientgen.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 7a7377f148..3b7669f33e 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -69,15 +69,36 @@ int cli_set_port(struct cli_state *cli, int port) static ssize_t client_receive_smb(struct cli_state *cli, size_t maxlen) { - ssize_t len; + size_t len; for(;;) { - len = receive_smb_raw(cli->fd, cli->inbuf, cli->timeout, - maxlen, &cli->smb_rw_error); + NTSTATUS status; - if (len < 0) { + set_smb_read_error(&cli->smb_rw_error, SMB_READ_OK); + + status = receive_smb_raw(cli->fd, cli->inbuf, cli->timeout, + maxlen, &len); + if (!NT_STATUS_IS_OK(status)) { DEBUG(10,("client_receive_smb failed\n")); show_msg(cli->inbuf); + + if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { + set_smb_read_error(&cli->smb_rw_error, + SMB_READ_EOF); + return -1; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { + set_smb_read_error(&cli->smb_rw_error, + SMB_READ_TIMEOUT); + return -1; + } + + set_smb_read_error(&cli->smb_rw_error, SMB_READ_ERROR); + return -1; + } + + if (len < 0) { return len; } -- cgit From 2a6a2288c5fae908f431bd79332554e0a23dbeed Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Fri, 8 Feb 2008 09:28:57 +0100 Subject: Fix some typos. Karolin (This used to be commit 2bec0a1fb7857e6fb8ec15e5f597b2d4125f105b) --- source3/libsmb/libsmbclient.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c index 2eb580a52d..e84de59637 100644 --- a/source3/libsmb/libsmbclient.c +++ b/source3/libsmb/libsmbclient.c @@ -6797,7 +6797,7 @@ smbc_free_context(SMBCCTX *context, SAFE_FREE(context->netbios_name); SAFE_FREE(context->user); - DEBUG(3, ("Context %p succesfully freed\n", context)); + DEBUG(3, ("Context %p successfully freed\n", context)); SAFE_FREE(context->internal); SAFE_FREE(context); return 0; -- cgit From c0e92cd4b8eae573848dc1587eecd2946715d754 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 Feb 2008 10:07:05 -0800 Subject: Fix bug reported on IRC enumerating shares with OS/2. Report and fix from kukks (thanks once again !). Jeremy. (This used to be commit 3ca58b792fb10ff2a4c25283c587f8270ed82d74) --- source3/libsmb/clirap.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c index 4c5e338606..8c167e1257 100644 --- a/source3/libsmb/clirap.c +++ b/source3/libsmb/clirap.c @@ -191,12 +191,13 @@ int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, co sname = p; type = SVAL(p,14); - comment_offset = IVAL(p,16) & 0xFFFF; - if (comment_offset < 0 || comment_offset > (int)rdrcnt) { + comment_offset = (IVAL(p,16) & 0xFFFF) - converter; + if (comment_offset < 0 || + comment_offset > (int)rdrcnt) { TALLOC_FREE(frame); break; } - cmnt = comment_offset?(rdata+comment_offset-converter):""; + cmnt = comment_offset?(rdata+comment_offset):""; /* Work out the comment length. */ for (p1 = cmnt, len = 0; *p1 && -- cgit From 48ea5852b6854f051754574b27807972426ebbbe Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 Feb 2008 11:22:53 -0800 Subject: Try and fix length and finfo calls for older clients. Working on issues reported by kukks. Jeremy. (This used to be commit dcd77dd4f480db3273a56c5740b6e5d78f8be4a9) --- source3/libsmb/clilist.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c index d5c7db09e9..2bad3e508b 100644 --- a/source3/libsmb/clilist.c +++ b/source3/libsmb/clilist.c @@ -459,11 +459,12 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, The length of the structure is returned. ****************************************************************************/ -static int interpret_short_filename(TALLOC_CTX *ctx, +static bool interpret_short_filename(TALLOC_CTX *ctx, struct cli_state *cli, char *p, file_info *finfo) { + size_t ret; ZERO_STRUCTP(finfo); finfo->cli = cli; @@ -475,18 +476,22 @@ static int interpret_short_filename(TALLOC_CTX *ctx, finfo->mtime_ts.tv_sec = finfo->atime_ts.tv_sec = finfo->ctime_ts.tv_sec; finfo->mtime_ts.tv_nsec = finfo->atime_ts.tv_nsec = 0; finfo->size = IVAL(p,26); - clistr_pull_talloc(ctx, + ret = clistr_pull_talloc(ctx, cli, &finfo->name, p+30, 12, STR_ASCII); - if (!finfo->name) { - finfo->name = talloc_strdup(ctx, finfo->short_name); - } else if (strcmp(finfo->name, "..") && strcmp(finfo->name, ".")) { - finfo->name = talloc_strdup(ctx, finfo->short_name); + if (ret == (size_t)-1) { + return false; } + if (finfo->name) { + strlcpy(finfo->short_name, + finfo->name, + sizeof(finfo->short_name)); + } + return true; return(DIR_STRUCT_SIZE); } @@ -555,6 +560,12 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute, received = SVAL(cli->inbuf,smb_vwv0); if (received <= 0) break; + /* Ensure we received enough data. */ + if ((cli->inbuf+4+smb_len(cli->inbuf) - (smb_buf(cli->inbuf)+3)) < + received*DIR_STRUCT_SIZE) { + break; + } + first = False; dirlist = (char *)SMB_REALLOC( @@ -609,7 +620,10 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute, frame = talloc_stackframe(); for (p=dirlist,i=0;i Date: Fri, 8 Feb 2008 18:44:33 -0800 Subject: From kukks - prevent crashes if finfo.name == NULL. Jeremy. (This used to be commit 101f194795f87c709abfdfbcde710131a88f9d20) --- source3/libsmb/clilist.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c index 2bad3e508b..2b5e7518c5 100644 --- a/source3/libsmb/clilist.c +++ b/source3/libsmb/clilist.c @@ -377,6 +377,12 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, &resume_key, &last_name_raw); + if (!finfo.name) { + DEBUG(0,("cli_list_new: Error: unable to parse name from info level %d\n", + info_level)); + ff_eos = 1; + break; + } if (!First && *mask && strcsequal(finfo.name, mask)) { DEBUG(0,("Error: Looping in FIND_NEXT as name %s has already been seen?\n", finfo.name)); @@ -442,6 +448,11 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, &finfo, NULL, NULL); + if (!finfo.name) { + DEBUG(0,("cli_list_new: unable to parse name from info level %d\n", + info_level)); + break; + } fn(mnt,&finfo, Mask, state); } } -- cgit From 0b583e4329a4a47918329d9022feb6ab8c54bb33 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 Feb 2008 19:02:49 -0800 Subject: Make clilist work again with OS/2 (kukks help!). Jeremy. (This used to be commit 2e27309401faa554620886b0e369db9d9c08e4fd) --- source3/libsmb/clilist.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c index 2b5e7518c5..d913096b12 100644 --- a/source3/libsmb/clilist.c +++ b/source3/libsmb/clilist.c @@ -78,9 +78,25 @@ static size_t interpret_long_filename(TALLOC_CTX *ctx, len = CVAL(p, 26); p += 27; p += clistr_align_in(cli, p, 0); - if (p + len + 2 > pdata_end) { + + /* We can safely use +1 here (which is required by OS/2) + * instead of +2 as the STR_TERMINATE flag below is + * actually used as the length calculation. + * The len+2 is merely an upper bound. + * We ensure we don't get a one byte overread by + * doing a zero termination at pdata_end[-1]; + * JRA + kukks */ + + if (p + len + 1 > pdata_end) { return pdata_end - base; } + + /* Ensure the null termination (see above). */ + { + char *pend = CONST_DISCARD(char *, pdata_end); + pend[-1] = '\0'; + } + /* the len+2 below looks strange but it is important to cope with the differences between win2000 and win9x for this call -- cgit From 20d6ebe813955866e70c0b91ef316830e1612437 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 Feb 2008 22:02:00 -0800 Subject: We don't need the extra null termination - we've already got this in the cli_receive_trans calls. Jeremy. (This used to be commit 99424bba7bb45b05d970bab4a5e93f2cb636fcbb) --- source3/libsmb/clilist.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c index d913096b12..e1b16154f2 100644 --- a/source3/libsmb/clilist.c +++ b/source3/libsmb/clilist.c @@ -83,20 +83,15 @@ static size_t interpret_long_filename(TALLOC_CTX *ctx, * instead of +2 as the STR_TERMINATE flag below is * actually used as the length calculation. * The len+2 is merely an upper bound. - * We ensure we don't get a one byte overread by - * doing a zero termination at pdata_end[-1]; - * JRA + kukks */ + * Due to the explicit 2 byte null termination + * in cli_receive_trans/cli_receive_nt_trans + * we know this is safe. JRA + kukks + */ if (p + len + 1 > pdata_end) { return pdata_end - base; } - /* Ensure the null termination (see above). */ - { - char *pend = CONST_DISCARD(char *, pdata_end); - pend[-1] = '\0'; - } - /* the len+2 below looks strange but it is important to cope with the differences between win2000 and win9x for this call -- cgit From b4dd60efa9d59dc70f0f0e58be6fa769c543d059 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 11 Feb 2008 18:36:06 +0100 Subject: Add a missing return If I'm not completely blind, we should return here. Not doing it here seems not to be a major flaw, as far as I can see we're only missing the error code. This might account for some of the very unhelpful NT_STATUS_UNSUCCESSFUL error messages people see during joins. All with stake in Samba client, please check! (This used to be commit eadd15c9363a57c214ede3c489057646baca48f8) --- source3/libsmb/cliconnect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index f3926b777b..e97be98fc1 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -627,7 +627,7 @@ static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char * if (!cli_session_setup_blob(cli, negTokenTarg, session_key_krb5)) { data_blob_free(&negTokenTarg); data_blob_free(&session_key_krb5); - ADS_ERROR_NT(cli_nt_error(cli)); + return ADS_ERROR_NT(cli_nt_error(cli)); } cli_set_session_key(cli, session_key_krb5); -- cgit From 0ba3d44f7321cb235eb214194395d5da02824690 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 13 Feb 2008 00:25:40 +0100 Subject: Use rpccli_lsa_EnumTrustDom all over the place. Guenther (This used to be commit a25e7ffbca9c2c97dd36b0596e7cb38a72aaf9d9) --- source3/libsmb/trusts_util.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c index 1ca7d56a83..11f691bee6 100644 --- a/source3/libsmb/trusts_util.c +++ b/source3/libsmb/trusts_util.c @@ -152,6 +152,8 @@ bool enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain, struct cli_state *cli = NULL; struct rpc_pipe_client *lsa_pipe; bool retry; + struct lsa_DomainList dom_list; + int i; *domain_names = NULL; *num_domains = 0; @@ -188,11 +190,33 @@ bool enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain, /* Lookup list of trusted domains */ - result = rpccli_lsa_enum_trust_dom(lsa_pipe, mem_ctx, &pol, &enum_ctx, - num_domains, domain_names, sids); + result = rpccli_lsa_EnumTrustDom(lsa_pipe, mem_ctx, + &pol, + &enum_ctx, + &dom_list, + (uint32_t)-1); if ( !NT_STATUS_IS_OK(result) ) goto done; + *num_domains = dom_list.count; + + *domain_names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_domains); + if (!*domain_names) { + result = NT_STATUS_NO_MEMORY; + goto done; + } + + *sids = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_domains); + if (!*sids) { + result = NT_STATUS_NO_MEMORY; + goto done; + } + + for (i=0; i< *num_domains; i++) { + (*domain_names)[i] = CONST_DISCARD(char *, dom_list.domains[i].name.string); + (*sids)[i] = *dom_list.domains[i].sid; + } + done: /* cleanup */ if (cli) { -- cgit From 39e0dbcf07251670b5475e9d0533c08a2712fffa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Feb 2008 11:29:54 -0800 Subject: Allow the mechOID to be written separately. Jeremy. (This used to be commit e3e08c6e7d270e1be7a9d3042b1f36f5a291f90a) --- source3/libsmb/clispnego.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clispnego.c b/source3/libsmb/clispnego.c index f95b11e4cd..a75032a47d 100644 --- a/source3/libsmb/clispnego.c +++ b/source3/libsmb/clispnego.c @@ -498,11 +498,13 @@ DATA_BLOB spnego_gen_auth_response(DATA_BLOB *reply, NTSTATUS nt_status, asn1_write_enumerated(&data, negResult); asn1_pop_tag(&data); - if (reply->data != NULL) { + if (mechOID) { asn1_push_tag(&data,ASN1_CONTEXT(1)); asn1_write_OID(&data, mechOID); asn1_pop_tag(&data); - + } + + if (reply && reply->data != NULL) { asn1_push_tag(&data,ASN1_CONTEXT(2)); asn1_write_OctetString(&data, reply->data, reply->length); asn1_pop_tag(&data); -- cgit From 401c0a6551efe2ac574d4fa0337c15ee2dd61da7 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 15 Feb 2008 13:51:54 +0100 Subject: Add netlogon_creds_client_check and netlogon_creds_client_step. Guenther (This used to be commit 41d33a2507e3fae7837bb8e42b1ac30cc31c31dc) --- source3/libsmb/credentials.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'source3/libsmb') diff --git a/source3/libsmb/credentials.c b/source3/libsmb/credentials.c index 1256a6210e..f03bf22df1 100644 --- a/source3/libsmb/credentials.c +++ b/source3/libsmb/credentials.c @@ -329,6 +329,25 @@ bool creds_client_check(const struct dcinfo *dc, const DOM_CHAL *rcv_srv_chal_in return True; } +bool netlogon_creds_client_check(const struct dcinfo *dc, + const struct netr_Credential *rcv_srv_chal_in) +{ + if (memcmp(dc->srv_chal.data, rcv_srv_chal_in->data, + sizeof(dc->srv_chal.data))) { + + DEBUG(0,("netlogon_creds_client_check: credentials check failed.\n")); + DEBUGADD(5,("netlogon_creds_client_check: challenge : %s\n", + credstr(rcv_srv_chal_in->data))); + DEBUGADD(5,("calculated: %s\n", credstr(dc->srv_chal.data))); + return false; + } + + DEBUG(10,("netlogon_creds_client_check: credentials check OK.\n")); + + return true; +} + + /**************************************************************************** Step the client credentials to the next element in the chain, updating the current client and server credentials and the seed @@ -345,3 +364,15 @@ void creds_client_step(struct dcinfo *dc, DOM_CRED *next_cred_out) next_cred_out->challenge = dc->clnt_chal; next_cred_out->timestamp.time = dc->sequence; } + +void netlogon_creds_client_step(struct dcinfo *dc, + struct netr_Authenticator *next_cred_out) +{ + dc->sequence += 2; + creds_step(dc); + creds_reseed(dc); + + memcpy(&next_cred_out->cred.data, &dc->clnt_chal.data, + sizeof(next_cred_out->cred.data)); + next_cred_out->timestamp = dc->sequence; +} -- cgit From f8bd3e82e5eda052ede2d294f08165cb23df9d90 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 15 Feb 2008 17:30:38 +0100 Subject: Add netlogon_creds_server_check and netlogon_creds_server_step. Guenther (This used to be commit ea0bf74918e7b009439452ea14ed68b0ce620787) --- source3/libsmb/credentials.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'source3/libsmb') diff --git a/source3/libsmb/credentials.c b/source3/libsmb/credentials.c index f03bf22df1..0043f4e6a9 100644 --- a/source3/libsmb/credentials.c +++ b/source3/libsmb/credentials.c @@ -225,6 +225,21 @@ bool creds_server_check(const struct dcinfo *dc, const DOM_CHAL *rcv_cli_chal_in return True; } +bool netlogon_creds_server_check(const struct dcinfo *dc, + const struct netr_Credential *rcv_cli_chal_in) +{ + if (memcmp(dc->clnt_chal.data, rcv_cli_chal_in->data, 8)) { + DEBUG(5,("netlogon_creds_server_check: challenge : %s\n", + credstr(rcv_cli_chal_in->data))); + DEBUG(5,("calculated: %s\n", credstr(dc->clnt_chal.data))); + DEBUG(2,("netlogon_creds_server_check: credentials check failed.\n")); + return false; + } + + DEBUG(10,("netlogon_creds_server_check: credentials check OK.\n")); + + return true; +} /**************************************************************************** Replace current seed chal. Internal function - due to split server step below. ****************************************************************************/ @@ -273,6 +288,36 @@ bool creds_server_step(struct dcinfo *dc, const DOM_CRED *received_cred, DOM_CRE return True; } +bool netlogon_creds_server_step(struct dcinfo *dc, + const struct netr_Authenticator *received_cred, + struct netr_Authenticator *cred_out) +{ + bool ret; + struct dcinfo tmp_dc = *dc; + + /* Do all operations on a temporary copy of the dc, + which we throw away if the checks fail. */ + + tmp_dc.sequence = received_cred->timestamp; + + creds_step(&tmp_dc); + + /* Create the outgoing credentials */ + cred_out->timestamp = tmp_dc.sequence + 1; + memcpy(&cred_out->cred, &tmp_dc.srv_chal, sizeof(cred_out->cred)); + + creds_reseed(&tmp_dc); + + ret = netlogon_creds_server_check(&tmp_dc, &received_cred->cred); + if (!ret) { + return false; + } + + /* creds step succeeded - replace the current creds. */ + *dc = tmp_dc; + return true; +} + /**************************************************************************** Create a client credential struct. ****************************************************************************/ -- cgit From 3f24ef18481417fd7d52856b3d68bec099a7b643 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 15 Feb 2008 23:57:19 +0100 Subject: Replace DOM_CHAL with "struct netr_Credential" where we can right now. This allows to remove some more old netlogon client calls. Guenther (This used to be commit c0b1a876583230a5130f5df1965d6c742961bcdc) --- source3/libsmb/credentials.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/credentials.c b/source3/libsmb/credentials.c index 0043f4e6a9..328b931df0 100644 --- a/source3/libsmb/credentials.c +++ b/source3/libsmb/credentials.c @@ -42,9 +42,9 @@ char *credstr(const unsigned char *cred) ****************************************************************************/ static void creds_init_128(struct dcinfo *dc, - const DOM_CHAL *clnt_chal_in, - const DOM_CHAL *srv_chal_in, - const unsigned char mach_pw[16]) + const struct netr_Credential *clnt_chal_in, + const struct netr_Credential *srv_chal_in, + const unsigned char mach_pw[16]) { unsigned char zero[4], tmp[16]; HMACMD5Context ctx; @@ -94,9 +94,9 @@ static void creds_init_128(struct dcinfo *dc, ****************************************************************************/ static void creds_init_64(struct dcinfo *dc, - const DOM_CHAL *clnt_chal_in, - const DOM_CHAL *srv_chal_in, - const unsigned char mach_pw[16]) + const struct netr_Credential *clnt_chal_in, + const struct netr_Credential *srv_chal_in, + const unsigned char mach_pw[16]) { uint32 sum[2]; unsigned char sum2[8]; @@ -177,10 +177,10 @@ static void creds_step(struct dcinfo *dc) void creds_server_init(uint32 neg_flags, struct dcinfo *dc, - DOM_CHAL *clnt_chal, - DOM_CHAL *srv_chal, + struct netr_Credential *clnt_chal, + struct netr_Credential *srv_chal, const unsigned char mach_pw[16], - DOM_CHAL *init_chal_out) + struct netr_Credential *init_chal_out) { DEBUG(10,("creds_server_init: neg_flags : %x\n", (unsigned int)neg_flags)); DEBUG(10,("creds_server_init: client chal : %s\n", credstr(clnt_chal->data) )); @@ -246,7 +246,7 @@ bool netlogon_creds_server_check(const struct dcinfo *dc, static void creds_reseed(struct dcinfo *dc) { - DOM_CHAL time_chal; + struct netr_Credential time_chal; SIVAL(time_chal.data, 0, IVAL(dc->seed_chal.data, 0) + dc->sequence + 1); SIVAL(time_chal.data, 4, IVAL(dc->seed_chal.data, 4)); @@ -274,7 +274,8 @@ bool creds_server_step(struct dcinfo *dc, const DOM_CRED *received_cred, DOM_CRE /* Create the outgoing credentials */ cred_out->timestamp.time = tmp_dc.sequence + 1; - cred_out->challenge = tmp_dc.srv_chal; + memcpy(&cred_out->challenge.data, tmp_dc.srv_chal.data, + sizeof(cred_out->challenge.data)); creds_reseed(&tmp_dc); @@ -324,10 +325,10 @@ bool netlogon_creds_server_step(struct dcinfo *dc, void creds_client_init(uint32 neg_flags, struct dcinfo *dc, - DOM_CHAL *clnt_chal, - DOM_CHAL *srv_chal, + struct netr_Credential *clnt_chal, + struct netr_Credential *srv_chal, const unsigned char mach_pw[16], - DOM_CHAL *init_chal_out) + struct netr_Credential *init_chal_out) { dc->sequence = time(NULL); @@ -406,7 +407,8 @@ void creds_client_step(struct dcinfo *dc, DOM_CRED *next_cred_out) creds_step(dc); creds_reseed(dc); - next_cred_out->challenge = dc->clnt_chal; + memcpy(&next_cred_out->challenge.data, dc->clnt_chal.data, + sizeof(next_cred_out->challenge.data)); next_cred_out->timestamp.time = dc->sequence; } -- cgit From b6285fc0526ff15250242489047bb8d49a1948e6 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sat, 16 Feb 2008 15:14:04 +0100 Subject: Remove unused creds_server_check and creds_server_step. Guenther (This used to be commit 2fb73a3545634982d17d3823cb629f06c5779fc0) --- source3/libsmb/credentials.c | 41 ----------------------------------------- 1 file changed, 41 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/credentials.c b/source3/libsmb/credentials.c index 328b931df0..2dcbdf3cf9 100644 --- a/source3/libsmb/credentials.c +++ b/source3/libsmb/credentials.c @@ -213,18 +213,6 @@ void creds_server_init(uint32 neg_flags, Check a credential sent by the client. ****************************************************************************/ -bool creds_server_check(const struct dcinfo *dc, const DOM_CHAL *rcv_cli_chal_in) -{ - if (memcmp(dc->clnt_chal.data, rcv_cli_chal_in->data, 8)) { - DEBUG(5,("creds_server_check: challenge : %s\n", credstr(rcv_cli_chal_in->data))); - DEBUG(5,("calculated: %s\n", credstr(dc->clnt_chal.data))); - DEBUG(2,("creds_server_check: credentials check failed.\n")); - return False; - } - DEBUG(10,("creds_server_check: credentials check OK.\n")); - return True; -} - bool netlogon_creds_server_check(const struct dcinfo *dc, const struct netr_Credential *rcv_cli_chal_in) { @@ -260,35 +248,6 @@ static void creds_reseed(struct dcinfo *dc) Step the server credential chain one forward. ****************************************************************************/ -bool creds_server_step(struct dcinfo *dc, const DOM_CRED *received_cred, DOM_CRED *cred_out) -{ - bool ret; - struct dcinfo tmp_dc = *dc; - - /* Do all operations on a temporary copy of the dc, - which we throw away if the checks fail. */ - - tmp_dc.sequence = received_cred->timestamp.time; - - creds_step(&tmp_dc); - - /* Create the outgoing credentials */ - cred_out->timestamp.time = tmp_dc.sequence + 1; - memcpy(&cred_out->challenge.data, tmp_dc.srv_chal.data, - sizeof(cred_out->challenge.data)); - - creds_reseed(&tmp_dc); - - ret = creds_server_check(&tmp_dc, &received_cred->challenge); - if (!ret) { - return False; - } - - /* creds step succeeded - replace the current creds. */ - *dc = tmp_dc; - return True; -} - bool netlogon_creds_server_step(struct dcinfo *dc, const struct netr_Authenticator *received_cred, struct netr_Authenticator *cred_out) -- cgit From dd65a349350717eb17257ccf281561dd878ead12 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sat, 16 Feb 2008 16:04:01 +0100 Subject: Use rpccli_netr_ServerPasswordSet in "just_change_the_password()". Guenther (This used to be commit 33f91c894488687a42500e751eb9016d99d9129c) --- source3/libsmb/trusts_util.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c index 11f691bee6..1e92bf21de 100644 --- a/source3/libsmb/trusts_util.c +++ b/source3/libsmb/trusts_util.c @@ -58,7 +58,32 @@ static NTSTATUS just_change_the_password(struct rpc_pipe_client *cli, TALLOC_CTX } } - result = rpccli_net_srv_pwset(cli, mem_ctx, global_myname(), new_trust_passwd_hash); + { + struct netr_Authenticator clnt_creds, srv_cred; + struct samr_Password new_password; + + netlogon_creds_client_step(cli->dc, &clnt_creds); + + cred_hash3(new_password.hash, + new_trust_passwd_hash, + cli->dc->sess_key, 1); + + result = rpccli_netr_ServerPasswordSet(cli, mem_ctx, + cli->dc->remote_machine, + cli->dc->mach_acct, + sec_channel_type, + global_myname(), + &clnt_creds, + &srv_cred, + &new_password); + + /* Always check returned credentials. */ + if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) { + DEBUG(0,("rpccli_netr_ServerPasswordSet: " + "credentials chain check failed\n")); + return NT_STATUS_ACCESS_DENIED; + } + } if (!NT_STATUS_IS_OK(result)) { DEBUG(0,("just_change_the_password: unable to change password (%s)!\n", -- cgit From 8027b7c25dfa5b4617c4fafbf1e4aaf4f7fee43a Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sun, 17 Feb 2008 01:47:01 +0100 Subject: Use netr_SamInfo3 in samlogon cache and use ndr functions for storing the blob. Guenther (This used to be commit bf860ae1ac6765b1eb6e2ca9b667b19b4e661fda) --- source3/libsmb/samlogon_cache.c | 217 ++++++++++++++++++++++------------------ 1 file changed, 119 insertions(+), 98 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/samlogon_cache.c b/source3/libsmb/samlogon_cache.c index 4f791f66f6..e2a4b3898f 100644 --- a/source3/libsmb/samlogon_cache.c +++ b/source3/libsmb/samlogon_cache.c @@ -1,21 +1,21 @@ -/* +/* Unix SMB/CIFS implementation. Net_sam_logon info3 helpers Copyright (C) Alexander Bokovoy 2002. Copyright (C) Andrew Bartlett 2002. Copyright (C) Gerald Carter 2003. Copyright (C) Tim Potter 2003. - + 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 . */ @@ -29,12 +29,12 @@ static TDB_CONTEXT *netsamlogon_tdb = NULL; /*********************************************************************** open the tdb ***********************************************************************/ - + bool netsamlogon_cache_init(void) { if (!netsamlogon_tdb) { netsamlogon_tdb = tdb_open_log(lock_path(NETSAMLOGON_TDB), 0, - TDB_DEFAULT, O_RDWR | O_CREAT, 0600); + TDB_DEFAULT, O_RDWR | O_CREAT, 0600); } return (netsamlogon_tdb != NULL); @@ -47,37 +47,39 @@ bool netsamlogon_cache_init(void) bool netsamlogon_cache_shutdown(void) { - if(netsamlogon_tdb) + if (netsamlogon_tdb) { return (tdb_close(netsamlogon_tdb) == 0); - - return True; + } + + return true; } /*********************************************************************** Clear cache getpwnam and getgroups entries from the winbindd cache ***********************************************************************/ -void netsamlogon_clear_cached_user(TDB_CONTEXT *tdb, NET_USER_INFO_3 *user) + +void netsamlogon_clear_cached_user(TDB_CONTEXT *tdb, struct netr_SamInfo3 *info3) { - bool got_tdb = False; + bool got_tdb = false; DOM_SID sid; fstring key_str, sid_string; /* We may need to call this function from smbd which will not have - winbindd_cache.tdb open. Open the tdb if a NULL is passed. */ + winbindd_cache.tdb open. Open the tdb if a NULL is passed. */ if (!tdb) { - tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), + tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE, TDB_DEFAULT, O_RDWR, 0600); if (!tdb) { DEBUG(5, ("netsamlogon_clear_cached_user: failed to open cache\n")); return; } - got_tdb = True; + got_tdb = true; } - sid_copy(&sid, &user->dom_sid.sid); - sid_append_rid(&sid, user->user_rid); + sid_copy(&sid, info3->base.domain_sid); + sid_append_rid(&sid, info3->base.rid); /* Clear U/SID cache entry */ @@ -95,157 +97,176 @@ void netsamlogon_clear_cached_user(TDB_CONTEXT *tdb, NET_USER_INFO_3 *user) tdb_delete(tdb, string_tdb_data(key_str)); - if (got_tdb) + if (got_tdb) { tdb_close(tdb); + } } /*********************************************************************** - Store a NET_USER_INFO_3 structure in a tdb for later user + Store a netr_SamInfo3 structure in a tdb for later user username should be in UTF-8 format ***********************************************************************/ -bool netsamlogon_cache_store( const char *username, NET_USER_INFO_3 *user ) +bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3) { - TDB_DATA data; - fstring keystr, tmp; - prs_struct ps; - bool result = False; - DOM_SID user_sid; - time_t t = time(NULL); - TALLOC_CTX *mem_ctx; - + TDB_DATA data; + fstring keystr, tmp; + bool result = false; + DOM_SID user_sid; + time_t t = time(NULL); + TALLOC_CTX *mem_ctx; + DATA_BLOB blob; + enum ndr_err_code ndr_err; + struct netsamlogoncache_entry r; + + if (!info3) { + return false; + } if (!netsamlogon_cache_init()) { - DEBUG(0,("netsamlogon_cache_store: cannot open %s for write!\n", NETSAMLOGON_TDB)); - return False; + DEBUG(0,("netsamlogon_cache_store: cannot open %s for write!\n", + NETSAMLOGON_TDB)); + return false; } - sid_copy( &user_sid, &user->dom_sid.sid ); - sid_append_rid( &user_sid, user->user_rid ); + sid_copy(&user_sid, info3->base.domain_sid); + sid_append_rid(&user_sid, info3->base.rid); /* Prepare key as DOMAIN-SID/USER-RID string */ slprintf(keystr, sizeof(keystr), "%s", sid_to_fstring(tmp, &user_sid)); DEBUG(10,("netsamlogon_cache_store: SID [%s]\n", keystr)); - + + /* Prepare data */ + + if (!(mem_ctx = TALLOC_P( NULL, int))) { + DEBUG(0,("netsamlogon_cache_store: talloc() failed!\n")); + return false; + } + /* only Samba fills in the username, not sure why NT doesn't */ /* so we fill it in since winbindd_getpwnam() makes use of it */ - - if ( !user->uni_user_name.buffer ) { - init_unistr2( &user->uni_user_name, username, UNI_STR_TERMINATE ); - init_uni_hdr( &user->hdr_user_name, &user->uni_user_name ); + + if (!info3->base.account_name.string) { + info3->base.account_name.string = talloc_strdup(mem_ctx, username); } - - /* Prepare data */ - - if ( !(mem_ctx = TALLOC_P( NULL, int )) ) { - DEBUG(0,("netsamlogon_cache_store: talloc() failed!\n")); - return False; + + r.timestamp = t; + r.info3 = *info3; + + if (DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(netsamlogoncache_entry, &r); } - prs_init( &ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - - { - uint32 ts = (uint32)t; - if ( !prs_uint32( "timestamp", &ps, 0, &ts ) ) - return False; + ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &r, + (ndr_push_flags_fn_t)ndr_push_netsamlogoncache_entry); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(0,("netsamlogon_cache_store: failed to push entry to cache\n")); + TALLOC_FREE(mem_ctx); + return false; } - - if ( net_io_user_info3("", user, &ps, 0, 3, 0) ) - { - data.dsize = prs_offset( &ps ); - data.dptr = (uint8 *)prs_data_p( &ps ); - if (tdb_store_bystring(netsamlogon_tdb, keystr, data, TDB_REPLACE) != -1) - result = True; - - prs_mem_free( &ps ); + data.dsize = blob.length; + data.dptr = blob.data; + + if (tdb_store_bystring(netsamlogon_tdb, keystr, data, TDB_REPLACE) != -1) { + result = true; } - TALLOC_FREE( mem_ctx ); - + TALLOC_FREE(mem_ctx); + return result; } /*********************************************************************** - Retrieves a NET_USER_INFO_3 structure from a tdb. Caller must + Retrieves a netr_SamInfo3 structure from a tdb. Caller must free the user_info struct (malloc()'d memory) ***********************************************************************/ -NET_USER_INFO_3* netsamlogon_cache_get( TALLOC_CTX *mem_ctx, const DOM_SID *user_sid) +struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid) { - NET_USER_INFO_3 *user = NULL; - TDB_DATA data; - prs_struct ps; - fstring keystr, tmp; - uint32 t; - + struct netr_SamInfo3 *info3 = NULL; + TDB_DATA data; + fstring keystr, tmp; + enum ndr_err_code ndr_err; + DATA_BLOB blob; + struct netsamlogoncache_entry r; + if (!netsamlogon_cache_init()) { - DEBUG(0,("netsamlogon_cache_get: cannot open %s for write!\n", NETSAMLOGON_TDB)); - return False; + DEBUG(0,("netsamlogon_cache_get: cannot open %s for write!\n", + NETSAMLOGON_TDB)); + return false; } /* Prepare key as DOMAIN-SID/USER-RID string */ slprintf(keystr, sizeof(keystr), "%s", sid_to_fstring(tmp, user_sid)); DEBUG(10,("netsamlogon_cache_get: SID [%s]\n", keystr)); data = tdb_fetch_bystring( netsamlogon_tdb, keystr ); - - if ( data.dptr ) { - user = TALLOC_ZERO_P(mem_ctx, NET_USER_INFO_3); - if (user == NULL) { - return NULL; - } + if (!data.dptr) { + return NULL; + } - prs_init( &ps, 0, mem_ctx, UNMARSHALL ); - prs_give_memory( &ps, (char *)data.dptr, data.dsize, True ); - - if ( !prs_uint32( "timestamp", &ps, 0, &t ) ) { - prs_mem_free( &ps ); - TALLOC_FREE(user); - return False; - } - - if ( !net_io_user_info3("", user, &ps, 0, 3, 0) ) { - TALLOC_FREE( user ); - } - - prs_mem_free( &ps ); + info3 = TALLOC_ZERO_P(mem_ctx, struct netr_SamInfo3); + if (!info3) { + goto done; + } + + blob.data = (uint8 *)data.dptr; + blob.length = data.dsize; + + ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r, + (ndr_pull_flags_fn_t)ndr_pull_netsamlogoncache_entry); -#if 0 /* The netsamlogon cache needs to hang around. Something about + if (DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(netsamlogoncache_entry, &r); + } + + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(0,("netsamlogon_cache_get: failed to pull entry from cache\n")); + tdb_delete(netsamlogon_tdb, data); + goto done; + } + + info3 = talloc_memdup(mem_ctx, &r.info3, sizeof(r.info3)); + + done: + SAFE_FREE(data.dptr); + + return info3; + +#if 0 /* The netsamlogon cache needs to hang around. Something about this feels wrong, but it is the only way we can get all of the groups. The old universal groups cache didn't expire either. --jerry */ { time_t now = time(NULL); uint32 time_diff; - + /* is the entry expired? */ time_diff = now - t; - + if ( (time_diff < 0 ) || (time_diff > lp_winbind_cache_time()) ) { DEBUG(10,("netsamlogon_cache_get: cache entry expired \n")); tdb_delete( netsamlogon_tdb, key ); TALLOC_FREE( user ); } -#endif } - - return user; +#endif } bool netsamlogon_cache_have(const DOM_SID *user_sid) { TALLOC_CTX *mem_ctx = talloc_init("netsamlogon_cache_have"); - NET_USER_INFO_3 *user = NULL; + struct netr_SamInfo3 *info3 = NULL; bool result; if (!mem_ctx) return False; - user = netsamlogon_cache_get(mem_ctx, user_sid); + info3 = netsamlogon_cache_get(mem_ctx, user_sid); - result = (user != NULL); + result = (info3 != NULL); talloc_destroy(mem_ctx); -- cgit From c1793b2b316a8f912dde14f806c84ac7d1491bf3 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sun, 17 Feb 2008 01:59:02 +0100 Subject: Use new IDL based PAC structures in clikrb5.c Guenther (This used to be commit 3b0135d57e1e70175a5eec49b603a2e5f700c770) --- source3/libsmb/clikrb5.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c index 844a3b35c0..c289740ab2 100644 --- a/source3/libsmb/clikrb5.c +++ b/source3/libsmb/clikrb5.c @@ -835,22 +835,22 @@ failed: #endif } - void smb_krb5_checksum_from_pac_sig(krb5_checksum *cksum, - PAC_SIGNATURE_DATA *sig) + void smb_krb5_checksum_from_pac_sig(krb5_checksum *cksum, + struct PAC_SIGNATURE_DATA *sig) { #ifdef HAVE_CHECKSUM_IN_KRB5_CHECKSUM cksum->cksumtype = (krb5_cksumtype)sig->type; - cksum->checksum.length = sig->signature.buf_len; - cksum->checksum.data = sig->signature.buffer; + cksum->checksum.length = sig->signature.length; + cksum->checksum.data = sig->signature.data; #else cksum->checksum_type = (krb5_cksumtype)sig->type; - cksum->length = sig->signature.buf_len; - cksum->contents = sig->signature.buffer; + cksum->length = sig->signature.length; + cksum->contents = sig->signature.data; #endif } krb5_error_code smb_krb5_verify_checksum(krb5_context context, - krb5_keyblock *keyblock, + const krb5_keyblock *keyblock, krb5_keyusage usage, krb5_checksum *cksum, uint8 *data, -- cgit From 5b8ebcf397e40bf1f9555c34fadbab2d7b5bf717 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sun, 17 Feb 2008 03:08:42 +0100 Subject: Remove unused creds_client_check and creds_client_step. Guenther (This used to be commit 1dcb32424d16cff968a8713352c93c48dec58674) --- source3/libsmb/credentials.c | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/credentials.c b/source3/libsmb/credentials.c index 2dcbdf3cf9..9d33e6d93d 100644 --- a/source3/libsmb/credentials.c +++ b/source3/libsmb/credentials.c @@ -322,18 +322,6 @@ void creds_client_init(uint32 neg_flags, Check a credential returned by the server. ****************************************************************************/ -bool creds_client_check(const struct dcinfo *dc, const DOM_CHAL *rcv_srv_chal_in) -{ - if (memcmp(dc->srv_chal.data, rcv_srv_chal_in->data, 8)) { - DEBUG(5,("creds_client_check: challenge : %s\n", credstr(rcv_srv_chal_in->data))); - DEBUG(5,("calculated: %s\n", credstr(dc->srv_chal.data))); - DEBUG(0,("creds_client_check: credentials check failed.\n")); - return False; - } - DEBUG(10,("creds_client_check: credentials check OK.\n")); - return True; -} - bool netlogon_creds_client_check(const struct dcinfo *dc, const struct netr_Credential *rcv_srv_chal_in) { @@ -360,17 +348,6 @@ bool netlogon_creds_client_check(const struct dcinfo *dc, the server ****************************************************************************/ -void creds_client_step(struct dcinfo *dc, DOM_CRED *next_cred_out) -{ - dc->sequence += 2; - creds_step(dc); - creds_reseed(dc); - - memcpy(&next_cred_out->challenge.data, dc->clnt_chal.data, - sizeof(next_cred_out->challenge.data)); - next_cred_out->timestamp.time = dc->sequence; -} - void netlogon_creds_client_step(struct dcinfo *dc, struct netr_Authenticator *next_cred_out) { -- cgit From 441de75e58daf734c412a3e741608822289cac59 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 18 Feb 2008 21:00:51 +1100 Subject: Fix memory leaks on error path (This used to be commit 47dd0700b4320bf5ac9a80e71ae82d82d4554e6a) --- source3/libsmb/clifile.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index 9b4c380d40..10c35a30cc 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -38,8 +38,15 @@ static bool cli_link_internal(struct cli_state *cli, const char *oldname, const size_t newlen = 2*(strlen(newname)+1); param = SMB_MALLOC_ARRAY(char, 6+newlen+2); + + if (!param) { + return false; + } + data = SMB_MALLOC_ARRAY(char, oldlen+2); - if (!param || !data) { + + if (!data) { + SAFE_FREE(param); return false; } -- cgit From 6548493de7680dedd429bf851fc57b577e06c673 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 23 Feb 2008 10:50:12 +0100 Subject: Fix a C++ warning (This used to be commit ac027a9b2e84d319f961ac0e84654a0e48920138) --- source3/libsmb/samlogon_cache.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/samlogon_cache.c b/source3/libsmb/samlogon_cache.c index e2a4b3898f..3cc0dcf0fb 100644 --- a/source3/libsmb/samlogon_cache.c +++ b/source3/libsmb/samlogon_cache.c @@ -228,7 +228,8 @@ struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const DOM_SID * goto done; } - info3 = talloc_memdup(mem_ctx, &r.info3, sizeof(r.info3)); + info3 = (struct netr_SamInfo3 *)talloc_memdup(mem_ctx, &r.info3, + sizeof(r.info3)); done: SAFE_FREE(data.dptr); -- cgit From a5e43bc81711e25cb07224df5e64f0120d4ef500 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 23 Feb 2008 21:40:39 +0100 Subject: Fix typo (This used to be commit 621db68f32f7007de8b2c4d7cf604a5778725615) --- source3/libsmb/cliconnect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index e97be98fc1..d88a5d6242 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -581,8 +581,8 @@ static bool cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob, DATA_B if (cli_is_error(cli) && !NT_STATUS_EQUAL( cli_get_nt_error(cli), NT_STATUS_MORE_PROCESSING_REQUIRED)) { - DEBUG(0, ("cli_session_setup_blob: recieve failed (%s)\n", - nt_errstr(cli_get_nt_error(cli)) )); + DEBUG(0, ("cli_session_setup_blob: receive failed " + "(%s)\n", nt_errstr(cli_get_nt_error(cli)))); cli->vuid = 0; return False; } -- cgit From 317639287886181edf08ccecad1b324e4cc55d0b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 25 Feb 2008 15:24:49 +0100 Subject: Fix some warnings warning: ignoring return value of 'asprintf', declared with attribute warn_unused_result (This used to be commit ad37b7b0aee265a3e4d8b7552610f4b9a105434d) --- source3/libsmb/clifsinfo.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c index fb923378ab..f4945f812a 100644 --- a/source3/libsmb/clifsinfo.c +++ b/source3/libsmb/clifsinfo.c @@ -497,8 +497,7 @@ static NTSTATUS make_cli_gss_blob(struct smb_trans_enc_state *es, memset(&tok_out, '\0', sizeof(tok_out)); /* Get a ticket for the service@host */ - asprintf(&host_princ_s, "%s@%s", service, host); - if (host_princ_s == NULL) { + if (asprintf(&host_princ_s, "%s@%s", service, host) == -1) { return NT_STATUS_NO_MEMORY; } -- cgit From c58e7427bf7200ad413c259f429f020b98d723ec Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Tue, 26 Feb 2008 21:42:26 -0500 Subject: add a function to truncate a file to a specified size (This used to be commit 7e5752812d6d9e3bcf9a545cbdcf3afe2175dbc4) --- source3/libsmb/clifile.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index 10c35a30cc..12c427a6fa 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -888,6 +888,55 @@ bool cli_close(struct cli_state *cli, int fnum) } +/**************************************************************************** + Truncate a file to a specified size +****************************************************************************/ + +bool cli_ftruncate(struct cli_state *cli, int fnum, uint64_t size) +{ + unsigned int param_len = 6; + unsigned int data_len = 8; + uint16 setup = TRANSACT2_SETFILEINFO; + char param[6]; + unsigned char data[8]; + char *rparam=NULL, *rdata=NULL; + int saved_timeout = cli->timeout; + + SSVAL(param,0,fnum); + SSVAL(param,2,SMB_SET_FILE_END_OF_FILE_INFO); + SSVAL(param,4,0); + + SBVAL(data, 0, size); + + if (!cli_send_trans(cli, SMBtrans2, + NULL, /* name */ + -1, 0, /* fid, flags */ + &setup, 1, 0, /* setup, length, max */ + param, param_len, 2, /* param, length, max */ + (char *)&data, data_len,/* data, length, ... */ + cli->max_xmit)) { /* ... max */ + cli->timeout = saved_timeout; + return False; + } + + if (!cli_receive_trans(cli, SMBtrans2, + &rparam, ¶m_len, + &rdata, &data_len)) { + cli->timeout = saved_timeout; + SAFE_FREE(rdata); + SAFE_FREE(rparam); + return False; + } + + cli->timeout = saved_timeout; + + SAFE_FREE(rdata); + SAFE_FREE(rparam); + + return True; +} + + /**************************************************************************** send a lock with a specified locktype this is used for testing LOCKING_ANDX_CANCEL_LOCK -- cgit From fa341d526293f4d986f2f3d838a728ce4223ee88 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Tue, 26 Feb 2008 21:44:51 -0500 Subject: add smbc_ftruncate() to emulate POSIX ftruncate() (This used to be commit 6f5051b9c1405ab1dc3e697419ceedb3acac46d8) --- source3/libsmb/libsmb_compat.c | 6 ++++ source3/libsmb/libsmbclient.c | 75 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) (limited to 'source3/libsmb') diff --git a/source3/libsmb/libsmb_compat.c b/source3/libsmb/libsmb_compat.c index 573d087d6e..6042464fd2 100644 --- a/source3/libsmb/libsmb_compat.c +++ b/source3/libsmb/libsmb_compat.c @@ -289,6 +289,12 @@ int smbc_fstat(int fd, struct stat *st) return (statcont->fstat)(statcont, file, st); } +int smbc_ftruncate(int fd, off_t size) +{ + SMBCFILE * file = find_fd(fd); + return (statcont->ftruncate)(statcont, file, size); +} + int smbc_chmod(const char *url, mode_t mode) { return (statcont->chmod)(statcont, url, mode); diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c index e84de59637..fe008ed6b6 100644 --- a/source3/libsmb/libsmbclient.c +++ b/source3/libsmb/libsmbclient.c @@ -2482,6 +2482,80 @@ smbc_fstat_ctx(SMBCCTX *context, } +/* + * Routine to truncate a file given by its file descriptor, to a specified size + */ + +static int +smbc_ftruncate_ctx(SMBCCTX *context, + SMBCFILE *file, + off_t length) +{ + SMB_OFF_T size = length; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *path = NULL; + char *targetpath = NULL; + struct cli_state *targetcli = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->internal || + !context->internal->_initialized) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!file || !DLIST_CONTAINS(context->internal->_files, file)) { + errno = EBADF; + TALLOC_FREE(frame); + return -1; + } + + if (!file->file) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + /*d_printf(">>>fstat: parsing %s\n", file->fname);*/ + if (smbc_parse_path(frame, + context, + file->fname, + NULL, + &server, + &share, + &path, + &user, + &password, + NULL)) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + /*d_printf(">>>fstat: resolving %s\n", path);*/ + if (!cli_resolve_path(frame, "", file->srv->cli, path, + &targetcli, &targetpath)) { + d_printf("Could not resolve %s\n", path); + TALLOC_FREE(frame); + return -1; + } + /*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/ + + if (!cli_ftruncate(targetcli, file->cli_fd, size)) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + TALLOC_FREE(frame); + return 0; + +} + /* * Routine to open a directory * We accept the URL syntax explained in smbc_parse_path(), above. @@ -6703,6 +6777,7 @@ smbc_new_context(void) context->telldir = smbc_telldir_ctx; context->lseekdir = smbc_lseekdir_ctx; context->fstatdir = smbc_fstatdir_ctx; + context->ftruncate = smbc_ftruncate_ctx; context->chmod = smbc_chmod_ctx; context->utimes = smbc_utimes_ctx; context->setxattr = smbc_setxattr_ctx; -- cgit From 2d01ec2c390f8dd753600f22cefb17e7b8916ffd Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 27 Feb 2008 15:49:31 +0100 Subject: Use new LSA_POLICY defines in lsa rpc server code and other places. Guenther (This used to be commit 58cca9faf9db506bd2f6eab4a99ef85153797ab2) --- source3/libsmb/trusts_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c index 1e92bf21de..c079fb149a 100644 --- a/source3/libsmb/trusts_util.c +++ b/source3/libsmb/trusts_util.c @@ -209,7 +209,7 @@ bool enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain, /* get a handle */ result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True, - POLICY_VIEW_LOCAL_INFORMATION, &pol); + LSA_POLICY_VIEW_LOCAL_INFORMATION, &pol); if ( !NT_STATUS_IS_OK(result) ) goto done; -- cgit From 7269a504fdd06fbbe24c2df8e084b41382d71269 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 27 Feb 2008 19:38:48 +0100 Subject: Add my copyright. Guenther (This used to be commit d078a8757182d84dfd3307a2e1b751cf173aaa97) --- source3/libsmb/samlogon_cache.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/libsmb') diff --git a/source3/libsmb/samlogon_cache.c b/source3/libsmb/samlogon_cache.c index 3cc0dcf0fb..0d855f4c6c 100644 --- a/source3/libsmb/samlogon_cache.c +++ b/source3/libsmb/samlogon_cache.c @@ -5,6 +5,7 @@ Copyright (C) Andrew Bartlett 2002. Copyright (C) Gerald Carter 2003. Copyright (C) Tim Potter 2003. + Copyright (C) Guenther Deschner 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 -- cgit From 1d940490e815bbdb7e4af23ace05ec9ac8fddae8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 28 Feb 2008 02:22:13 -0800 Subject: Fix from Guenter Kukkukk to fix listing against OS/2 servers. OS/2 returns eclass == ERRDOS && ecode == ERRnofiles for a zero entry directory listing. Jeremy. (This used to be commit b34da627053581a9584367e177566d4a2cef7e82) --- source3/libsmb/clierror.c | 12 ++++++++++++ source3/libsmb/clilist.c | 16 +++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clierror.c b/source3/libsmb/clierror.c index 587abade59..36746419f7 100644 --- a/source3/libsmb/clierror.c +++ b/source3/libsmb/clierror.c @@ -483,3 +483,15 @@ void cli_set_nt_error(struct cli_state *cli, NTSTATUS status) SSVAL(cli->inbuf,smb_flg2, SVAL(cli->inbuf,smb_flg2)|FLAGS2_32_BIT_ERROR_CODES); SIVAL(cli->inbuf, smb_rcls, NT_STATUS_V(status)); } + +/* Reset an error. */ + +void cli_reset_error(struct cli_state *cli) +{ + if (SVAL(cli->inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES) { + SIVAL(cli->inbuf, smb_rcls, NT_STATUS_V(NT_STATUS_OK)); + } else { + SCVAL(cli->inbuf,smb_rcls,0); + SSVAL(cli->inbuf,smb_err,0); + } +} diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c index e1b16154f2..50918458b0 100644 --- a/source3/libsmb/clilist.c +++ b/source3/libsmb/clilist.c @@ -328,7 +328,7 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, &rparam, ¶m_len, &rdata, &data_len) && cli_is_dos_error(cli)) { - /* we need to work around a Win95 bug - sometimes + /* We need to work around a Win95 bug - sometimes it gives ERRSRV/ERRerror temprarily */ uint8 eclass; uint32 ecode; @@ -337,6 +337,20 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, SAFE_FREE(rparam); cli_dos_error(cli, &eclass, &ecode); + + /* + * OS/2 might return "no more files", + * which just tells us, that searchcount is zero + * in this search. + * Guenter Kukkukk + */ + + if (eclass == ERRDOS && ecode == ERRnofiles) { + ff_searchcount = 0; + cli_reset_error(cli); + break; + } + if (eclass != ERRSRV || ecode != ERRerror) break; smb_msleep(100); -- cgit From 0d8985f2da43d35d8f940af112ad74a199778dd8 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 28 Feb 2008 12:30:18 +0100 Subject: Let dsgetdcname() return a struct netr_DsRGetDCNameInfo. Guenther (This used to be commit b1a4b21f8c35dc23e5c986ebe44d3806055eb39b) --- source3/libsmb/dsgetdcname.c | 144 ++++++++++++++++++++----------------------- 1 file changed, 67 insertions(+), 77 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c index e0be76cc85..bc9f4b92c8 100644 --- a/source3/libsmb/dsgetdcname.c +++ b/source3/libsmb/dsgetdcname.c @@ -110,7 +110,7 @@ void debug_dsdcinfo_flags(int lvl, uint32_t flags) /********************************************************************* ********************************************************************/ -static int pack_dsdcinfo(struct DS_DOMAIN_CONTROLLER_INFO *info, +static int pack_dsdcinfo(struct netr_DsRGetDCNameInfo *info, unsigned char **buf) { unsigned char *buffer = NULL; @@ -122,9 +122,8 @@ static int pack_dsdcinfo(struct DS_DOMAIN_CONTROLLER_INFO *info, ZERO_STRUCT(guid_flat); - if (info->domain_guid) { - const struct GUID *guid = info->domain_guid; - smb_uuid_pack(*guid, &guid_flat); + if (!GUID_all_zero(&info->domain_guid)) { + smb_uuid_pack(info->domain_guid, &guid_flat); } again: @@ -132,17 +131,17 @@ static int pack_dsdcinfo(struct DS_DOMAIN_CONTROLLER_INFO *info, if (buflen > 0) { DEBUG(10,("pack_dsdcinfo: Packing domain %s (%s)\n", - info->domain_name, info->domain_controller_name)); + info->domain_name, info->dc_unc)); } len += tdb_pack(buffer+len, buflen-len, "ffdBffdff", - info->domain_controller_name, - info->domain_controller_address, - info->domain_controller_address_type, + info->dc_unc, + info->dc_address, + info->dc_address_type, UUID_FLAT_SIZE, guid_flat.info, info->domain_name, - info->dns_forest_name, - info->flags, + info->forest_name, + info->dc_flags, info->dc_site_name, info->client_site_name); @@ -169,33 +168,33 @@ static int pack_dsdcinfo(struct DS_DOMAIN_CONTROLLER_INFO *info, static NTSTATUS unpack_dsdcinfo(TALLOC_CTX *mem_ctx, unsigned char *buf, int buflen, - struct DS_DOMAIN_CONTROLLER_INFO **info_ret) + struct netr_DsRGetDCNameInfo **info_ret) { int len = 0; - struct DS_DOMAIN_CONTROLLER_INFO *info = NULL; + struct netr_DsRGetDCNameInfo *info = NULL; uint32_t guid_len = 0; unsigned char *guid_buf = NULL; UUID_FLAT guid_flat; /* forgive me 6 times */ - fstring domain_controller_name; - fstring domain_controller_address; + fstring dc_unc; + fstring dc_address; fstring domain_name; - fstring dns_forest_name; + fstring forest_name; fstring dc_site_name; fstring client_site_name; - info = TALLOC_ZERO_P(mem_ctx, struct DS_DOMAIN_CONTROLLER_INFO); + info = TALLOC_ZERO_P(mem_ctx, struct netr_DsRGetDCNameInfo); NT_STATUS_HAVE_NO_MEMORY(info); len += tdb_unpack(buf+len, buflen-len, "ffdBffdff", - &domain_controller_name, - &domain_controller_address, - &info->domain_controller_address_type, + &dc_unc, + &dc_address, + &info->dc_address_type, &guid_len, &guid_buf, &domain_name, - &dns_forest_name, - &info->flags, + &forest_name, + &info->dc_flags, &dc_site_name, &client_site_name); if (len == -1) { @@ -203,23 +202,23 @@ static NTSTATUS unpack_dsdcinfo(TALLOC_CTX *mem_ctx, goto failed; } - info->domain_controller_name = - talloc_strdup(mem_ctx, domain_controller_name); - info->domain_controller_address = - talloc_strdup(mem_ctx, domain_controller_address); + info->dc_unc = + talloc_strdup(mem_ctx, dc_unc); + info->dc_address = + talloc_strdup(mem_ctx, dc_address); info->domain_name = talloc_strdup(mem_ctx, domain_name); - info->dns_forest_name = - talloc_strdup(mem_ctx, dns_forest_name); + info->forest_name = + talloc_strdup(mem_ctx, forest_name); info->dc_site_name = talloc_strdup(mem_ctx, dc_site_name); info->client_site_name = talloc_strdup(mem_ctx, client_site_name); - if (!info->domain_controller_name || - !info->domain_controller_address || + if (!info->dc_unc || + !info->dc_address || !info->domain_name || - !info->dns_forest_name || + !info->forest_name || !info->dc_site_name || !info->client_site_name) { goto failed; @@ -235,16 +234,12 @@ static NTSTATUS unpack_dsdcinfo(TALLOC_CTX *mem_ctx, memcpy(&guid_flat.info, guid_buf, guid_len); smb_uuid_unpack(guid_flat, &guid); - info->domain_guid = (struct GUID *)talloc_memdup( - mem_ctx, &guid, sizeof(guid)); - if (!info->domain_guid) { - goto failed; - } + info->domain_guid = guid; SAFE_FREE(guid_buf); } DEBUG(10,("unpack_dcscinfo: Unpacked domain %s (%s)\n", - info->domain_name, info->domain_controller_name)); + info->domain_name, info->dc_unc)); *info_ret = info; @@ -297,7 +292,7 @@ static NTSTATUS dsgetdcname_cache_delete(TALLOC_CTX *mem_ctx, static NTSTATUS dsgetdcname_cache_store(TALLOC_CTX *mem_ctx, const char *domain_name, - struct DS_DOMAIN_CONTROLLER_INFO *info) + struct netr_DsRGetDCNameInfo *info) { time_t expire_time; char *key; @@ -346,7 +341,7 @@ static NTSTATUS dsgetdcname_cache_refresh(TALLOC_CTX *mem_ctx, struct GUID *domain_guid, uint32_t flags, const char *site_name, - struct DS_DOMAIN_CONTROLLER_INFO *info) + struct netr_DsRGetDCNameInfo *info) { struct cldap_netlogon_reply r; @@ -355,7 +350,7 @@ static NTSTATUS dsgetdcname_cache_refresh(TALLOC_CTX *mem_ctx, ZERO_STRUCT(r); - if (ads_cldap_netlogon(info->domain_controller_name, + if (ads_cldap_netlogon(info->dc_unc, info->domain_name, &r)) { dsgetdcname_cache_delete(mem_ctx, domain_name); @@ -409,7 +404,7 @@ static NTSTATUS dsgetdcname_cache_fetch(TALLOC_CTX *mem_ctx, struct GUID *domain_guid, uint32_t flags, const char *site_name, - struct DS_DOMAIN_CONTROLLER_INFO **info, + struct netr_DsRGetDCNameInfo **info, bool *expired) { char *key; @@ -438,13 +433,13 @@ static NTSTATUS dsgetdcname_cache_fetch(TALLOC_CTX *mem_ctx, data_blob_free(&blob); /* check flags */ - if (!check_cldap_reply_required_flags((*info)->flags, flags)) { + if (!check_cldap_reply_required_flags((*info)->dc_flags, flags)) { DEBUG(10,("invalid flags\n")); return NT_STATUS_INVALID_PARAMETER; } if ((flags & DS_IP_REQUIRED) && - ((*info)->domain_controller_address_type != ADS_INET_ADDRESS)) { + ((*info)->dc_address_type != DS_ADDRESS_TYPE_INET)) { return NT_STATUS_INVALID_PARAMETER_MIX; } @@ -459,7 +454,7 @@ static NTSTATUS dsgetdcname_cached(TALLOC_CTX *mem_ctx, struct GUID *domain_guid, uint32_t flags, const char *site_name, - struct DS_DOMAIN_CONTROLLER_INFO **info) + struct netr_DsRGetDCNameInfo **info) { NTSTATUS status; bool expired = false; @@ -663,40 +658,36 @@ static NTSTATUS discover_dc_dns(TALLOC_CTX *mem_ctx, ****************************************************************/ static NTSTATUS make_domain_controller_info(TALLOC_CTX *mem_ctx, - const char *domain_controller_name, - const char *domain_controller_address, - uint32_t domain_controller_address_type, + const char *dc_unc, + const char *dc_address, + uint32_t dc_address_type, const struct GUID *domain_guid, const char *domain_name, - const char *dns_forest_name, + const char *forest_name, uint32_t flags, const char *dc_site_name, const char *client_site_name, - struct DS_DOMAIN_CONTROLLER_INFO **info_out) + struct netr_DsRGetDCNameInfo **info_out) { - struct DS_DOMAIN_CONTROLLER_INFO *info; + struct netr_DsRGetDCNameInfo *info; - info = TALLOC_ZERO_P(mem_ctx, struct DS_DOMAIN_CONTROLLER_INFO); + info = TALLOC_ZERO_P(mem_ctx, struct netr_DsRGetDCNameInfo); NT_STATUS_HAVE_NO_MEMORY(info); - if (domain_controller_name) { - info->domain_controller_name = talloc_strdup(mem_ctx, - domain_controller_name); - NT_STATUS_HAVE_NO_MEMORY(info->domain_controller_name); + if (dc_unc) { + info->dc_unc = talloc_strdup(mem_ctx, dc_unc); + NT_STATUS_HAVE_NO_MEMORY(info->dc_unc); } - if (domain_controller_address) { - info->domain_controller_address = talloc_strdup(mem_ctx, - domain_controller_address); - NT_STATUS_HAVE_NO_MEMORY(info->domain_controller_address); + if (dc_address) { + info->dc_address = talloc_strdup(mem_ctx, dc_address); + NT_STATUS_HAVE_NO_MEMORY(info->dc_address); } - info->domain_controller_address_type = domain_controller_address_type; + info->dc_address_type = dc_address_type; if (domain_guid) { - info->domain_guid = (struct GUID *)talloc_memdup( - mem_ctx, domain_guid, sizeof(*domain_guid)); - NT_STATUS_HAVE_NO_MEMORY(info->domain_guid); + info->domain_guid = *domain_guid; } if (domain_name) { @@ -704,13 +695,12 @@ static NTSTATUS make_domain_controller_info(TALLOC_CTX *mem_ctx, NT_STATUS_HAVE_NO_MEMORY(info->domain_name); } - if (dns_forest_name) { - info->dns_forest_name = talloc_strdup(mem_ctx, - dns_forest_name); - NT_STATUS_HAVE_NO_MEMORY(info->dns_forest_name); + if (forest_name) { + info->forest_name = talloc_strdup(mem_ctx, forest_name); + NT_STATUS_HAVE_NO_MEMORY(info->forest_name); } - info->flags = flags; + info->dc_flags = flags; if (dc_site_name) { info->dc_site_name = talloc_strdup(mem_ctx, dc_site_name); @@ -736,7 +726,7 @@ static NTSTATUS process_dc_dns(TALLOC_CTX *mem_ctx, uint32_t flags, struct ip_service_name **dclist, int num_dcs, - struct DS_DOMAIN_CONTROLLER_INFO **info) + struct netr_DsRGetDCNameInfo **info) { int i = 0; bool valid_dc = false; @@ -779,12 +769,12 @@ static NTSTATUS process_dc_dns(TALLOC_CTX *mem_ctx, } dc_hostname = r.hostname; dc_domain_name = r.domain; - dc_flags |= ADS_DNS_DOMAIN | ADS_DNS_CONTROLLER; + dc_flags |= DS_DNS_DOMAIN | DS_DNS_CONTROLLER; } else { /* FIXME */ dc_hostname = r.hostname; dc_domain_name = r.domain; - dc_flags |= ADS_DNS_DOMAIN | ADS_DNS_CONTROLLER; + dc_flags |= DS_DNS_DOMAIN | DS_DNS_CONTROLLER; } if (flags & DS_IP_REQUIRED) { @@ -792,17 +782,17 @@ static NTSTATUS process_dc_dns(TALLOC_CTX *mem_ctx, print_sockaddr(addr, sizeof(addr), &dclist[i]->ss); dc_address = talloc_asprintf(mem_ctx, "\\\\%s", addr); - dc_address_type = ADS_INET_ADDRESS; + dc_address_type = DS_ADDRESS_TYPE_INET; } else { dc_address = talloc_asprintf(mem_ctx, "\\\\%s", r.netbios_hostname); - dc_address_type = ADS_NETBIOS_ADDRESS; + dc_address_type = DS_ADDRESS_TYPE_NETBIOS; } NT_STATUS_HAVE_NO_MEMORY(dc_address); smb_uuid_unpack(r.guid, &dc_guid); if (r.forest) { - dc_flags |= ADS_DNS_FOREST; + dc_flags |= DS_DNS_FOREST; } return make_domain_controller_info(mem_ctx, @@ -827,7 +817,7 @@ static NTSTATUS process_dc_netbios(TALLOC_CTX *mem_ctx, uint32_t flags, struct ip_service_name **dclist, int num_dcs, - struct DS_DOMAIN_CONTROLLER_INFO **info) + struct netr_DsRGetDCNameInfo **info) { /* FIXME: code here */ @@ -842,7 +832,7 @@ static NTSTATUS dsgetdcname_rediscover(TALLOC_CTX *mem_ctx, struct GUID *domain_guid, uint32_t flags, const char *site_name, - struct DS_DOMAIN_CONTROLLER_INFO **info) + struct netr_DsRGetDCNameInfo **info) { NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; struct ip_service_name *dclist; @@ -901,10 +891,10 @@ NTSTATUS dsgetdcname(TALLOC_CTX *mem_ctx, struct GUID *domain_guid, const char *site_name, uint32_t flags, - struct DS_DOMAIN_CONTROLLER_INFO **info) + struct netr_DsRGetDCNameInfo **info) { NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; - struct DS_DOMAIN_CONTROLLER_INFO *myinfo = NULL; + struct netr_DsRGetDCNameInfo *myinfo = NULL; DEBUG(10,("dsgetdcname: domain_name: %s, " "domain_guid: %s, site_name: %s, flags: 0x%08x\n", -- cgit From 4b5169f590425334d9ae3f2b7be2201e2e0b747e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 12 Feb 2008 11:54:37 +0100 Subject: Add explicit buf arg to cli_encrypt_message and cli_calculate_sign_mac (This used to be commit db6ae9ed2326e6cd68475375d049084cf1d5a98c) --- source3/libsmb/cliconnect.c | 2 +- source3/libsmb/clientgen.c | 5 +++-- source3/libsmb/smb_seal.c | 6 +++--- source3/libsmb/smb_signing.c | 4 ++-- 4 files changed, 9 insertions(+), 8 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index d88a5d6242..9c27d30166 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -757,7 +757,7 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use /* 'resign' the last message, so we get the right sequence numbers for checking the first reply from the server */ - cli_calculate_sign_mac(cli); + cli_calculate_sign_mac(cli, cli->outbuf); if (!cli_check_sign_mac(cli)) { nt_status = NT_STATUS_ACCESS_DENIED; diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 3b7669f33e..2fd304f135 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -343,10 +343,11 @@ bool cli_send_smb(struct cli_state *cli) if (cli->fd == -1) return false; - cli_calculate_sign_mac(cli); + cli_calculate_sign_mac(cli, cli->outbuf); if (enc_on) { - NTSTATUS status = cli_encrypt_message(cli, &buf_out); + NTSTATUS status = cli_encrypt_message(cli, cli->outbuf, + &buf_out); if (!NT_STATUS_IS_OK(status)) { close(cli->fd); cli->fd = -1; diff --git a/source3/libsmb/smb_seal.c b/source3/libsmb/smb_seal.c index b5befbf7cd..a81ae9afd5 100644 --- a/source3/libsmb/smb_seal.c +++ b/source3/libsmb/smb_seal.c @@ -483,15 +483,15 @@ NTSTATUS cli_decrypt_message(struct cli_state *cli) Encrypt an outgoing buffer. Return the encrypted pointer in buf_out. ******************************************************************************/ -NTSTATUS cli_encrypt_message(struct cli_state *cli, char **buf_out) +NTSTATUS cli_encrypt_message(struct cli_state *cli, char *buf, char **buf_out) { /* Ignore non-session messages. */ - if(CVAL(cli->outbuf,0)) { + if (CVAL(buf,0)) { return NT_STATUS_OK; } /* If we supported multiple encrytion contexts * here we'd look up based on tid. */ - return common_encrypt_buffer(cli->trans_enc_state, cli->outbuf, buf_out); + return common_encrypt_buffer(cli->trans_enc_state, buf, buf_out); } diff --git a/source3/libsmb/smb_signing.c b/source3/libsmb/smb_signing.c index f03c21bd0e..eeaf28c3d1 100644 --- a/source3/libsmb/smb_signing.c +++ b/source3/libsmb/smb_signing.c @@ -573,9 +573,9 @@ void cli_free_signing_context(struct cli_state *cli) * Sign a packet with the current mechanism */ -void cli_calculate_sign_mac(struct cli_state *cli) +void cli_calculate_sign_mac(struct cli_state *cli, char *buf) { - cli->sign_info.sign_outgoing_message(cli->outbuf, &cli->sign_info); + cli->sign_info.sign_outgoing_message(buf, &cli->sign_info); } /** -- cgit From b9f7dd2909487f8e306774ee0475f8b20331a866 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 12 Feb 2008 23:16:37 +0100 Subject: Add explicit buf arg to cli_check_sign_mac (This used to be commit ffc1c8cc03e6bad40ed2be91392074b4f038a1bf) --- source3/libsmb/cliconnect.c | 2 +- source3/libsmb/clientgen.c | 2 +- source3/libsmb/smb_signing.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 9c27d30166..912b841d5e 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -759,7 +759,7 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use for checking the first reply from the server */ cli_calculate_sign_mac(cli, cli->outbuf); - if (!cli_check_sign_mac(cli)) { + if (!cli_check_sign_mac(cli, cli->inbuf)) { nt_status = NT_STATUS_ACCESS_DENIED; } } diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 2fd304f135..ccd1cc67d5 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -164,7 +164,7 @@ bool cli_receive_smb(struct cli_state *cli) return false; } - if (!cli_check_sign_mac(cli)) { + if (!cli_check_sign_mac(cli, cli->inbuf)) { /* * If we get a signature failure in sessionsetup, then * the server sometimes just reflects the sent signature diff --git a/source3/libsmb/smb_signing.c b/source3/libsmb/smb_signing.c index eeaf28c3d1..bd6d97123d 100644 --- a/source3/libsmb/smb_signing.c +++ b/source3/libsmb/smb_signing.c @@ -584,9 +584,9 @@ void cli_calculate_sign_mac(struct cli_state *cli, char *buf) * which had a bad checksum, True otherwise. */ -bool cli_check_sign_mac(struct cli_state *cli) +bool cli_check_sign_mac(struct cli_state *cli, char *buf) { - if (!cli->sign_info.check_incoming_message(cli->inbuf, &cli->sign_info, True)) { + if (!cli->sign_info.check_incoming_message(buf, &cli->sign_info, True)) { free_signing_context(&cli->sign_info); return False; } -- cgit From 11b81cb8e419315abc8bf2d7b1a93424aa9788e9 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 28 Feb 2008 13:58:34 +0100 Subject: Add WERR_TIME_SKEW to werror mapping tables. Guenther (This used to be commit 74767be627d48eb1a8deea3784847159b536a0fb) --- source3/libsmb/doserr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/libsmb') diff --git a/source3/libsmb/doserr.c b/source3/libsmb/doserr.c index a3043a2152..203f682599 100644 --- a/source3/libsmb/doserr.c +++ b/source3/libsmb/doserr.c @@ -84,6 +84,7 @@ werror_code_struct dos_errs[] = { "WERR_LOGON_FAILURE", WERR_LOGON_FAILURE }, { "WERR_NO_SUCH_DOMAIN", WERR_NO_SUCH_DOMAIN }, { "WERR_INVALID_SECURITY_DESCRIPTOR", WERR_INVALID_SECURITY_DESCRIPTOR }, + { "WERR_TIME_SKEW", WERR_TIME_SKEW }, { "WERR_INVALID_OWNER", WERR_INVALID_OWNER }, { "WERR_SERVER_UNAVAILABLE", WERR_SERVER_UNAVAILABLE }, { "WERR_IO_PENDING", WERR_IO_PENDING }, @@ -121,6 +122,7 @@ werror_str_struct dos_err_strs[] = { { WERR_USER_EXISTS, "User account already exists" }, { WERR_PASSWORD_MUST_CHANGE, "The password must be changed" }, { WERR_ACCOUNT_LOCKED_OUT, "Account locked out" }, + { WERR_TIME_SKEW, "Time difference between client and server" }, }; /***************************************************************************** -- cgit From 57a9fba097a5f5af7833eaf4355667dbfacaec43 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 28 Feb 2008 14:03:38 +0100 Subject: Make cli_struct a talloc parent (This used to be commit e69244a5c8c7c6b7c1897adc4b4b1cfdfc7a7999) --- source3/libsmb/clientgen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index ccd1cc67d5..592f050e90 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -537,7 +537,7 @@ struct cli_state *cli_initialise(void) return NULL; } - cli = SMB_MALLOC_P(struct cli_state); + cli = talloc(NULL, struct cli_state); if (!cli) { return NULL; } @@ -695,7 +695,7 @@ void cli_shutdown(struct cli_state *cli) cli->fd = -1; cli->smb_rw_error = SMB_READ_OK; - SAFE_FREE(cli); + TALLOC_FREE(cli); } /**************************************************************************** -- cgit From be4a76a861f3a152f1d1aebf937b06e1628f2d55 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 28 Feb 2008 14:04:54 +0100 Subject: Add cli_setup_packet_buf This is == cli_setup_packet but takes an explicit buffer argument (This used to be commit f64b46dc278899c3449cfd3dbb614aadcf5614d3) --- source3/libsmb/clientgen.c | 54 +++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 22 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 592f050e90..64191239d3 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -450,31 +450,41 @@ bool cli_send_smb_direct_writeX(struct cli_state *cli, Setup basics in a outgoing packet. ****************************************************************************/ -void cli_setup_packet(struct cli_state *cli) +void cli_setup_packet_buf(struct cli_state *cli, char *buf) { + uint16 flags2; cli->rap_error = 0; - SSVAL(cli->outbuf,smb_pid,cli->pid); - SSVAL(cli->outbuf,smb_uid,cli->vuid); - SSVAL(cli->outbuf,smb_mid,cli->mid); - if (cli->protocol > PROTOCOL_CORE) { - uint16 flags2; - if (cli->case_sensitive) { - SCVAL(cli->outbuf,smb_flg,0x0); - } else { - /* Default setting, case insensitive. */ - SCVAL(cli->outbuf,smb_flg,0x8); - } - flags2 = FLAGS2_LONG_PATH_COMPONENTS; - if (cli->capabilities & CAP_UNICODE) - flags2 |= FLAGS2_UNICODE_STRINGS; - if ((cli->capabilities & CAP_DFS) && cli->dfsroot) - flags2 |= FLAGS2_DFS_PATHNAMES; - if (cli->capabilities & CAP_STATUS32) - flags2 |= FLAGS2_32_BIT_ERROR_CODES; - if (cli->use_spnego) - flags2 |= FLAGS2_EXTENDED_SECURITY; - SSVAL(cli->outbuf,smb_flg2, flags2); + SIVAL(buf,smb_rcls,0); + SSVAL(buf,smb_pid,cli->pid); + memset(buf+smb_pidhigh, 0, 12); + SSVAL(buf,smb_uid,cli->vuid); + SSVAL(buf,smb_mid,cli->mid); + + if (cli->protocol <= PROTOCOL_CORE) { + return; + } + + if (cli->case_sensitive) { + SCVAL(buf,smb_flg,0x0); + } else { + /* Default setting, case insensitive. */ + SCVAL(buf,smb_flg,0x8); } + flags2 = FLAGS2_LONG_PATH_COMPONENTS; + if (cli->capabilities & CAP_UNICODE) + flags2 |= FLAGS2_UNICODE_STRINGS; + if ((cli->capabilities & CAP_DFS) && cli->dfsroot) + flags2 |= FLAGS2_DFS_PATHNAMES; + if (cli->capabilities & CAP_STATUS32) + flags2 |= FLAGS2_32_BIT_ERROR_CODES; + if (cli->use_spnego) + flags2 |= FLAGS2_EXTENDED_SECURITY; + SSVAL(buf,smb_flg2, flags2); +} + +void cli_setup_packet(struct cli_state *cli) +{ + cli_setup_packet_buf(cli, cli->outbuf); } /**************************************************************************** -- cgit From 6e2e0e2ce7ebef473cf8f8787363500eb090d692 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 28 Feb 2008 06:01:09 -0800 Subject: Fix the build - don't use SMB_TRANS_ENC_GSS without KRB5. Jeremy. (This used to be commit d16c295642c3df49be02440427ded0cd9b4179f5) --- source3/libsmb/clifsinfo.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c index f4945f812a..0005c3908a 100644 --- a/source3/libsmb/clifsinfo.c +++ b/source3/libsmb/clifsinfo.c @@ -368,20 +368,16 @@ static struct smb_trans_enc_state *make_cli_enc_state(enum smb_trans_enc_type sm ZERO_STRUCTP(es); es->smb_enc_type = smb_enc_type; - if (smb_enc_type == SMB_TRANS_ENC_GSS) { #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) + if (smb_enc_type == SMB_TRANS_ENC_GSS) { es->s.gss_state = SMB_MALLOC_P(struct smb_tran_enc_state_gss); if (!es->s.gss_state) { SAFE_FREE(es); return NULL; } ZERO_STRUCTP(es->s.gss_state); -#else - DEBUG(0,("make_cli_enc_state: no krb5 compiled.\n")); - SAFE_FREE(es); - return NULL; -#endif } +#endif return es; } -- cgit From 1d41b5bd2a58dcc6966a3a49ccb063ff05e46125 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 28 Feb 2008 14:41:25 +0100 Subject: Add infrastructure to support async SMB requests (This used to be commit f5356825698a02df2d400b51dd95d1f857c83e81) --- source3/libsmb/async_smb.c | 483 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 483 insertions(+) create mode 100644 source3/libsmb/async_smb.c (limited to 'source3/libsmb') diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c new file mode 100644 index 0000000000..21bcd5b9b1 --- /dev/null +++ b/source3/libsmb/async_smb.c @@ -0,0 +1,483 @@ +/* + Unix SMB/CIFS implementation. + Infrastructure for async SMB client requests + Copyright (C) Volker Lendecke 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" + +/* + * Fetch an error out of a NBT packet + */ + +NTSTATUS cli_pull_error(char *buf) +{ + uint32_t flags2 = SVAL(buf, smb_flg2); + + if (flags2 & FLAGS2_32_BIT_ERROR_CODES) { + return NT_STATUS(IVAL(buf, smb_rcls)); + } + + return NT_STATUS_DOS(CVAL(buf, smb_rcls), SVAL(buf,smb_err)); +} + +/* + * Compatibility helper for the sync APIs: Fake NTSTATUS in cli->inbuf + */ + +void cli_set_error(struct cli_state *cli, NTSTATUS status) +{ + uint32_t flags2 = SVAL(cli->inbuf, smb_flg2); + + if (NT_STATUS_IS_DOS(status)) { + SSVAL(cli->inbuf, smb_flg2, + flags2 & ~FLAGS2_32_BIT_ERROR_CODES); + SCVAL(cli->inbuf, smb_rcls, NT_STATUS_DOS_CLASS(status)); + SSVAL(cli->inbuf, smb_err, NT_STATUS_DOS_CODE(status)); + return; + } + + SSVAL(cli->inbuf, smb_flg2, flags2 | FLAGS2_32_BIT_ERROR_CODES); + SIVAL(cli->inbuf, smb_rcls, NT_STATUS_V(status)); + return; +} + +/* + * Allocate a new mid + */ + +static uint16_t cli_new_mid(struct cli_state *cli) +{ + uint16_t result; + struct cli_request *req; + + while (true) { + result = cli->mid++; + if (result == 0) { + continue; + } + + for (req = cli->outstanding_requests; req; req = req->next) { + if (result == req->mid) { + break; + } + } + + if (req == NULL) { + return result; + } + } +} + +static char *cli_request_print(TALLOC_CTX *mem_ctx, struct async_req *req) +{ + char *result = async_req_print(mem_ctx, req); + struct cli_request *cli_req = cli_request_get(req); + + if (result == NULL) { + return NULL; + } + + return talloc_asprintf_append_buffer( + result, "mid=%d\n", cli_req->mid); +} + +static int cli_request_destructor(struct cli_request *req) +{ + if (req->enc_state != NULL) { + common_free_enc_buffer(req->enc_state, req->outbuf); + } + DLIST_REMOVE(req->cli->outstanding_requests, req); + return 0; +} + +/* + * Create a fresh async smb request + */ + +struct async_req *cli_request_new(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint8_t num_words, size_t num_bytes, + struct cli_request **preq) +{ + struct async_req *result; + struct cli_request *cli_req; + size_t bufsize = smb_size + num_words * 2 + num_bytes; + + result = async_req_new(mem_ctx, ev); + if (result == NULL) { + return NULL; + } + + cli_req = (struct cli_request *)talloc_size( + result, sizeof(*cli_req) + bufsize); + if (cli_req == NULL) { + TALLOC_FREE(result); + return NULL; + } + talloc_set_name_const(cli_req, "struct cli_request"); + result->private_data = cli_req; + result->print = cli_request_print; + + cli_req->async = result; + cli_req->cli = cli; + cli_req->outbuf = ((char *)cli_req + sizeof(*cli_req)); + cli_req->sent = 0; + cli_req->mid = cli_new_mid(cli); + cli_req->inbuf = NULL; + cli_req->enc_state = NULL; + + SCVAL(cli_req->outbuf, smb_wct, num_words); + SSVAL(cli_req->outbuf, smb_vwv + num_words * 2, num_bytes); + + DLIST_ADD_END(cli->outstanding_requests, cli_req, + struct cli_request *); + talloc_set_destructor(cli_req, cli_request_destructor); + + DEBUG(10, ("cli_request_new: mid=%d\n", cli_req->mid)); + + *preq = cli_req; + return result; +} + +/* + * Convenience function to get the SMB part out of an async_req + */ + +struct cli_request *cli_request_get(struct async_req *req) +{ + if (req == NULL) { + return NULL; + } + return talloc_get_type_abort(req->private_data, struct cli_request); +} + +/* + * A PDU has arrived on cli->evt_inbuf + */ + +static void handle_incoming_pdu(struct cli_state *cli) +{ + struct cli_request *req; + uint16_t mid; + size_t raw_pdu_len, buf_len, pdu_len; + size_t rest_len; + NTSTATUS status; + + /* + * The encrypted PDU len might differ from the unencrypted one + */ + raw_pdu_len = smb_len(cli->evt_inbuf) + 4; + + /* + * TODO: Handle oplock break requests + */ + + if (cli_encryption_on(cli) && CVAL(cli->evt_inbuf, 0) == 0) { + uint16_t enc_ctx_num; + + status = get_enc_ctx_num((uint8_t *)cli->evt_inbuf, + &enc_ctx_num); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("get_enc_ctx_num returned %s\n", + nt_errstr(status))); + goto invalidate_requests; + } + + if (enc_ctx_num != cli->trans_enc_state->enc_ctx_num) { + DEBUG(10, ("wrong enc_ctx %d, expected %d\n", + enc_ctx_num, + cli->trans_enc_state->enc_ctx_num)); + status = NT_STATUS_INVALID_HANDLE; + goto invalidate_requests; + } + + status = common_decrypt_buffer(cli->trans_enc_state, + cli->evt_inbuf); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("common_decrypt_buffer returned %s\n", + nt_errstr(status))); + goto invalidate_requests; + } + } + + if (!cli_check_sign_mac(cli, cli->evt_inbuf)) { + DEBUG(10, ("cli_check_sign_mac failed\n")); + status = NT_STATUS_ACCESS_DENIED; + goto invalidate_requests; + } + + mid = SVAL(cli->evt_inbuf, smb_mid); + + DEBUG(10, ("handle_incoming_pdu: got mid %d\n", mid)); + + for (req = cli->outstanding_requests; req; req = req->next) { + if (req->mid == mid) { + break; + } + } + + buf_len = talloc_get_size(cli->evt_inbuf); + pdu_len = smb_len(cli->evt_inbuf) + 4; + rest_len = buf_len - raw_pdu_len; + + if (req == NULL) { + DEBUG(3, ("Request for mid %d not found, dumping PDU\n", mid)); + + memmove(cli->evt_inbuf, cli->evt_inbuf + raw_pdu_len, + buf_len - raw_pdu_len); + + cli->evt_inbuf = TALLOC_REALLOC_ARRAY(NULL, cli->evt_inbuf, + char, rest_len); + return; + } + + if (buf_len == pdu_len) { + /* + * Optimal case: Exactly one PDU was in the socket buffer + */ + req->inbuf = talloc_move(req, &cli->evt_inbuf); + goto done; + } + + DEBUG(11, ("buf_len = %d, pdu_len = %d, splitting buffer\n", + (int)buf_len, (int)pdu_len)); + + if (pdu_len < rest_len) { + /* + * The PDU is shorter, talloc_memdup that one. + */ + req->inbuf = (char *)talloc_memdup( + req, cli->evt_inbuf, pdu_len); + + memmove(cli->evt_inbuf, + cli->evt_inbuf + raw_pdu_len, + buf_len - raw_pdu_len); + + cli->evt_inbuf = TALLOC_REALLOC_ARRAY( + NULL, cli->evt_inbuf, char, rest_len); + } + else { + /* + * The PDU is larger than the rest, + * talloc_memdup the rest + */ + req->inbuf = talloc_move(req, &cli->evt_inbuf); + + cli->evt_inbuf = (char *)talloc_memdup( + cli, req->inbuf + raw_pdu_len, + rest_len); + } + + if ((req->inbuf == NULL) || (cli->evt_inbuf == NULL)) { + status = NT_STATUS_NO_MEMORY; + goto invalidate_requests; + } + + done: + async_req_done(req->async); + return; + + invalidate_requests: + + DEBUG(10, ("handle_incoming_pdu: Aborting with %s\n", + nt_errstr(status))); + + for (req = cli->outstanding_requests; req; req = req->next) { + async_req_error(req->async, status); + } + return; +} + +/* + * fd event callback. This is the basic connection to the socket + */ + +static void cli_state_handler(struct event_context *event_ctx, + struct fd_event *event, uint16 flags, void *p) +{ + struct cli_state *cli = (struct cli_state *)p; + struct cli_request *req; + + DEBUG(11, ("cli_state_handler called with flags %d\n", flags)); + + if (flags & EVENT_FD_READ) { + int res, available; + size_t old_size, new_size; + char *tmp; + + res = ioctl(cli->fd, FIONREAD, &available); + if (res == -1) { + DEBUG(10, ("ioctl(FIONREAD) failed: %s\n", + strerror(errno))); + goto sock_error; + } + + if (available == 0) { + /* EOF */ + goto sock_error; + } + + old_size = talloc_get_size(cli->evt_inbuf); + new_size = old_size + available; + + if (new_size < old_size) { + /* wrap */ + goto sock_error; + } + + tmp = TALLOC_REALLOC_ARRAY(cli, cli->evt_inbuf, char, + new_size); + if (tmp == NULL) { + /* nomem */ + goto sock_error; + } + cli->evt_inbuf = tmp; + + res = recv(cli->fd, cli->evt_inbuf + old_size, available, 0); + if (res == -1) { + DEBUG(10, ("recv failed: %s\n", strerror(errno))); + goto sock_error; + } + + DEBUG(11, ("cli_state_handler: received %d bytes, " + "smb_len(evt_inbuf) = %d\n", (int)res, + smb_len(cli->evt_inbuf))); + + /* recv *might* have returned less than announced */ + new_size = old_size + res; + + /* shrink, so I don't expect errors here */ + cli->evt_inbuf = TALLOC_REALLOC_ARRAY(cli, cli->evt_inbuf, + char, new_size); + + while ((cli->evt_inbuf != NULL) + && ((smb_len(cli->evt_inbuf) + 4) <= new_size)) { + /* + * we've got a complete NBT level PDU in evt_inbuf + */ + handle_incoming_pdu(cli); + new_size = talloc_get_size(cli->evt_inbuf); + } + } + + if (flags & EVENT_FD_WRITE) { + size_t to_send; + ssize_t sent; + + for (req = cli->outstanding_requests; req; req = req->next) { + to_send = smb_len(req->outbuf)+4; + if (to_send > req->sent) { + break; + } + } + + if (req == NULL) { + event_fd_set_not_writeable(event); + return; + } + + sent = send(cli->fd, req->outbuf + req->sent, + to_send - req->sent, 0); + + if (sent < 0) { + goto sock_error; + } + + req->sent += sent; + + if (req->sent == to_send) { + return; + } + } + return; + + sock_error: + for (req = cli->outstanding_requests; req; req = req->next) { + req->async->state = ASYNC_REQ_ERROR; + req->async->status = map_nt_error_from_unix(errno); + } + TALLOC_FREE(cli->fd_event); + close(cli->fd); + cli->fd = -1; +} + +/* + * Holder for a talloc_destructor, we need to zero out the pointers in cli + * when deleting + */ +struct cli_tmp_event { + struct cli_state *cli; +}; + +static int cli_tmp_event_destructor(struct cli_tmp_event *e) +{ + TALLOC_FREE(e->cli->fd_event); + TALLOC_FREE(e->cli->event_ctx); + return 0; +} + +/* + * Create a temporary event context for use in the sync helper functions + */ + +struct cli_tmp_event *cli_tmp_event_ctx(TALLOC_CTX *mem_ctx, + struct cli_state *cli) +{ + struct cli_tmp_event *state; + + if (cli->event_ctx != NULL) { + return NULL; + } + + state = talloc(mem_ctx, struct cli_tmp_event); + if (state == NULL) { + return NULL; + } + state->cli = cli; + talloc_set_destructor(state, cli_tmp_event_destructor); + + cli->event_ctx = event_context_init(state); + if (cli->event_ctx == NULL) { + TALLOC_FREE(state); + return NULL; + } + + cli->fd_event = event_add_fd(cli->event_ctx, state, cli->fd, + EVENT_FD_READ, cli_state_handler, cli); + if (cli->fd_event == NULL) { + TALLOC_FREE(state); + return NULL; + } + return state; +} + +/* + * Attach an event context permanently to a cli_struct + */ + +NTSTATUS cli_add_event_ctx(struct cli_state *cli, + struct event_context *event_ctx) +{ + cli->event_ctx = event_ctx; + cli->fd_event = event_add_fd(event_ctx, cli, cli->fd, EVENT_FD_READ, + cli_state_handler, cli); + if (cli->fd_event == NULL) { + return NT_STATUS_NO_MEMORY; + } + return NT_STATUS_OK; +} -- cgit From 525aac775ecef275dbd0732830a9bac0fd023135 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 28 Feb 2008 15:21:33 +0100 Subject: Add async cli_pull support This is the big (and potentially controversial) one. It took a phone call to explain to metze what is going on inside cli_pull_read_done, but I would really like everybody to understand this function. It is a very good and reasonably complex example of async programming. If we want more asynchronism in s3, this is what we will have to deal with :-) Make use of it in the smbclient "get" command. Volker (This used to be commit 844a163458c7585e4306a21ffdae5d08e03d6e4d) --- source3/libsmb/clireadwrite.c | 425 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 425 insertions(+) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index af13ed8f73..5aee8f18bd 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -19,6 +19,431 @@ #include "includes.h" +/**************************************************************************** + Calculate the recommended read buffer size +****************************************************************************/ +static size_t cli_read_max_bufsize(struct cli_state *cli) +{ + if (!client_is_signing_on(cli) && !cli_encryption_on(cli) == false + && (cli->posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) { + return CLI_SAMBA_MAX_POSIX_LARGE_READX_SIZE; + } + if (cli->capabilities & CAP_LARGE_READX) { + return cli->is_samba + ? CLI_SAMBA_MAX_LARGE_READX_SIZE + : CLI_WINDOWS_MAX_LARGE_READX_SIZE; + } + return (cli->max_xmit - (smb_size+32)) & ~1023; +} + +/* + * Send a read&x request + */ + +struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, + struct cli_state *cli, int fnum, + off_t offset, size_t size) +{ + struct async_req *result; + struct cli_request *req; + bool bigoffset = False; + char *enc_buf; + + if (size > cli_read_max_bufsize(cli)) { + DEBUG(0, ("cli_read_andx_send got size=%d, can only handle " + "size=%d\n", (int)size, + (int)cli_read_max_bufsize(cli))); + return NULL; + } + + result = cli_request_new(mem_ctx, cli->event_ctx, cli, 12, 0, &req); + if (result == NULL) { + DEBUG(0, ("cli_request_new failed\n")); + return NULL; + } + + req = cli_request_get(result); + + req->data.read.ofs = offset; + req->data.read.size = size; + req->data.read.received = 0; + req->data.read.rcvbuf = NULL; + + if ((SMB_BIG_UINT)offset >> 32) + bigoffset = True; + + cli_set_message(req->outbuf, bigoffset ? 12 : 10, 0, False); + + SCVAL(req->outbuf,smb_com,SMBreadX); + SSVAL(req->outbuf,smb_tid,cli->cnum); + cli_setup_packet_buf(cli, req->outbuf); + + SCVAL(req->outbuf,smb_vwv0,0xFF); + SCVAL(req->outbuf,smb_vwv0+1,0); + SSVAL(req->outbuf,smb_vwv1,0); + SSVAL(req->outbuf,smb_vwv2,fnum); + SIVAL(req->outbuf,smb_vwv3,offset); + SSVAL(req->outbuf,smb_vwv5,size); + SSVAL(req->outbuf,smb_vwv6,size); + SSVAL(req->outbuf,smb_vwv7,(size >> 16)); + SSVAL(req->outbuf,smb_vwv8,0); + SSVAL(req->outbuf,smb_vwv9,0); + SSVAL(req->outbuf,smb_mid,req->mid); + + if (bigoffset) { + SIVAL(req->outbuf, smb_vwv10, + (((SMB_BIG_UINT)offset)>>32) & 0xffffffff); + } + + cli_calculate_sign_mac(cli, req->outbuf); + + event_fd_set_writeable(cli->fd_event); + + if (cli_encryption_on(cli)) { + NTSTATUS status; + status = cli_encrypt_message(cli, req->outbuf, &enc_buf); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Error in encrypting client message. " + "Error %s\n", nt_errstr(status))); + TALLOC_FREE(req); + return NULL; + } + req->outbuf = enc_buf; + req->enc_state = cli->trans_enc_state; + } + + return result; +} + +/* + * Pull the data out of a finished async read_and_x request. rcvbuf is + * talloced from the request, so better make sure that you copy it away before + * you talloc_free(req). "rcvbuf" is NOT a talloc_ctx of its own, so do not + * talloc_move it! + */ + +NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, + uint8_t **rcvbuf) +{ + struct cli_request *cli_req = cli_request_get(req); + NTSTATUS status; + size_t size; + + SMB_ASSERT(req->state >= ASYNC_REQ_DONE); + if (req->state == ASYNC_REQ_ERROR) { + return req->status; + } + + status = cli_pull_error(cli_req->inbuf); + + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* size is the number of bytes the server returned. + * Might be zero. */ + size = SVAL(cli_req->inbuf, smb_vwv5); + size |= (((unsigned int)(SVAL(cli_req->inbuf, smb_vwv7))) << 16); + + if (size > cli_req->data.read.size) { + DEBUG(5,("server returned more than we wanted!\n")); + return NT_STATUS_UNEXPECTED_IO_ERROR; + } + + if (size < 0) { + DEBUG(5,("read return < 0!\n")); + return NT_STATUS_UNEXPECTED_IO_ERROR; + } + + *rcvbuf = (uint8_t *) + (smb_base(cli_req->inbuf) + SVAL(cli_req->inbuf, smb_vwv6)); + *received = size; + return NT_STATUS_OK; +} + +/* + * Parallel read support. + * + * cli_pull sends as many read&x requests as the server would allow via + * max_mux at a time. When replies flow back in, the data is written into + * the callback function "sink" in the right order. + */ + +struct cli_pull_state { + struct async_req *req; + + struct cli_state *cli; + uint16_t fnum; + off_t start_offset; + size_t size; + + NTSTATUS (*sink)(char *buf, size_t n, void *priv); + void *priv; + + size_t chunk_size; + + /* + * Outstanding requests + */ + int num_reqs; + struct async_req **reqs; + + /* + * For how many bytes did we send requests already? + */ + off_t requested; + + /* + * Next request index to push into "sink". This walks around the "req" + * array, taking care that the requests are pushed to "sink" in the + * right order. If necessary (i.e. replies don't come in in the right + * order), replies are held back in "reqs". + */ + int top_req; + + /* + * How many bytes did we push into "sink"? + */ + + off_t pushed; +}; + +static char *cli_pull_print(TALLOC_CTX *mem_ctx, struct async_req *req) +{ + struct cli_pull_state *state = talloc_get_type_abort( + req->private_data, struct cli_pull_state); + char *result; + + result = async_req_print(mem_ctx, req); + if (result == NULL) { + return NULL; + } + + return talloc_asprintf_append_buffer( + result, "num_reqs=%d, top_req=%d", + state->num_reqs, state->top_req); +} + +static void cli_pull_read_done(struct async_req *read_req); + +/* + * Prepare an async pull request + */ + +struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, + uint16_t fnum, off_t start_offset, + size_t size, size_t window_size, + NTSTATUS (*sink)(char *buf, size_t n, + void *priv), + void *priv) +{ + struct async_req *result; + struct cli_pull_state *state; + int i; + + result = async_req_new(mem_ctx, cli->event_ctx); + if (result == NULL) { + goto failed; + } + state = talloc(result, struct cli_pull_state); + if (state == NULL) { + goto failed; + } + result->private_data = state; + result->print = cli_pull_print; + state->req = result; + + state->cli = cli; + state->fnum = fnum; + state->start_offset = start_offset; + state->size = size; + state->sink = sink; + state->priv = priv; + + state->pushed = 0; + state->top_req = 0; + state->chunk_size = cli_read_max_bufsize(cli); + + state->num_reqs = MAX(window_size/state->chunk_size, 1); + state->num_reqs = MIN(state->num_reqs, cli->max_mux); + + state->reqs = TALLOC_ZERO_ARRAY(state, struct async_req *, + state->num_reqs); + if (state->reqs == NULL) { + goto failed; + } + + state->requested = 0; + + for (i=0; inum_reqs; i++) { + size_t size_left, request_thistime; + + if (state->requested >= size) { + state->num_reqs = i; + break; + } + + size_left = size - state->requested; + request_thistime = MIN(size_left, state->chunk_size); + + state->reqs[i] = cli_read_andx_send( + state->reqs, cli, fnum, + state->start_offset + state->requested, + request_thistime); + + if (state->reqs[i] == NULL) { + goto failed; + } + + state->reqs[i]->async.fn = cli_pull_read_done; + state->reqs[i]->async.priv = result; + + state->requested += request_thistime; + } + return result; + +failed: + TALLOC_FREE(result); + return NULL; +} + +/* + * Handle incoming read replies, push the data into sink and send out new + * requests if necessary. + */ + +static void cli_pull_read_done(struct async_req *read_req) +{ + struct async_req *pull_req = talloc_get_type_abort( + read_req->async.priv, struct async_req); + struct cli_pull_state *state = talloc_get_type_abort( + pull_req->private_data, struct cli_pull_state); + struct cli_request *read_state = cli_request_get(read_req); + NTSTATUS status; + + status = cli_read_andx_recv(read_req, &read_state->data.read.received, + &read_state->data.read.rcvbuf); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(state->req, status); + return; + } + + /* + * This loop is the one to take care of out-of-order replies. All + * pending requests are in state->reqs, state->reqs[top_req] is the + * one that is to be pushed next. If however a request later than + * top_req is replied to, then we can't push yet. If top_req is + * replied to at a later point then, we need to push all the finished + * requests. + */ + + while (state->reqs[state->top_req] != NULL) { + struct cli_request *top_read; + + DEBUG(11, ("cli_pull_read_done: top_req = %d\n", + state->top_req)); + + if (state->reqs[state->top_req]->state < ASYNC_REQ_DONE) { + DEBUG(11, ("cli_pull_read_done: top request not yet " + "done\n")); + return; + } + + top_read = cli_request_get(state->reqs[state->top_req]); + + DEBUG(10, ("cli_pull_read_done: Pushing %d bytes, %d already " + "pushed\n", (int)top_read->data.read.received, + (int)state->pushed)); + + status = state->sink((char *)top_read->data.read.rcvbuf, + top_read->data.read.received, + state->priv); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(state->req, status); + return; + } + state->pushed += top_read->data.read.received; + + TALLOC_FREE(state->reqs[state->top_req]); + + if (state->requested < state->size) { + struct async_req *new_req; + size_t size_left, request_thistime; + + size_left = state->size - state->requested; + request_thistime = MIN(size_left, state->chunk_size); + + DEBUG(10, ("cli_pull_read_done: Requesting %d bytes " + "at %d, position %d\n", + (int)request_thistime, + (int)(state->start_offset + + state->requested), + state->top_req)); + + new_req = cli_read_andx_send( + state->reqs, state->cli, state->fnum, + state->start_offset + state->requested, + request_thistime); + + if (async_req_nomem(new_req, state->req)) { + return; + } + + new_req->async.fn = cli_pull_read_done; + new_req->async.priv = pull_req; + + state->reqs[state->top_req] = new_req; + state->requested += request_thistime; + } + + state->top_req = (state->top_req+1) % state->num_reqs; + } + + async_req_done(pull_req); +} + +NTSTATUS cli_pull_recv(struct async_req *req, ssize_t *received) +{ + struct cli_pull_state *state = talloc_get_type_abort( + req->private_data, struct cli_pull_state); + + SMB_ASSERT(req->state >= ASYNC_REQ_DONE); + if (req->state == ASYNC_REQ_ERROR) { + return req->status; + } + *received = state->pushed; + return NT_STATUS_OK; +} + +NTSTATUS cli_pull(struct cli_state *cli, uint16_t fnum, + off_t start_offset, size_t size, size_t window_size, + NTSTATUS (*sink)(char *buf, size_t n, void *priv), + void *priv, ssize_t *received) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct async_req *req; + NTSTATUS result = NT_STATUS_NO_MEMORY; + + if (cli_tmp_event_ctx(frame, cli) == NULL) { + goto nomem; + } + + req = cli_pull_send(frame, cli, fnum, start_offset, size, window_size, + sink, priv); + if (req == NULL) { + goto nomem; + } + + while (req->state < ASYNC_REQ_DONE) { + event_loop_once(cli->event_ctx); + } + + result = cli_pull_recv(req, received); + nomem: + TALLOC_FREE(frame); + return result; +} + /**************************************************************************** Issue a single SMBread and don't wait for a reply. ****************************************************************************/ -- cgit From 95222d115a1ab676ecebdaa30d627608afb9758f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 28 Feb 2008 15:26:01 +0100 Subject: Convert cli_read to use cli_pull (This used to be commit 719527f55e88f0c5fdceda5c807475aba299c79f) --- source3/libsmb/clireadwrite.c | 178 ++++-------------------------------------- 1 file changed, 15 insertions(+), 163 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 5aee8f18bd..c618509f01 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -444,175 +444,27 @@ NTSTATUS cli_pull(struct cli_state *cli, uint16_t fnum, return result; } -/**************************************************************************** -Issue a single SMBread and don't wait for a reply. -****************************************************************************/ - -static bool cli_issue_read(struct cli_state *cli, int fnum, off_t offset, - size_t size, int i) +static NTSTATUS cli_read_sink(char *buf, size_t n, void *priv) { - bool bigoffset = False; - - memset(cli->outbuf,'\0',smb_size); - memset(cli->inbuf,'\0',smb_size); - - if ((SMB_BIG_UINT)offset >> 32) - bigoffset = True; - - cli_set_message(cli->outbuf,bigoffset ? 12 : 10,0,True); - - SCVAL(cli->outbuf,smb_com,SMBreadX); - SSVAL(cli->outbuf,smb_tid,cli->cnum); - cli_setup_packet(cli); - - SCVAL(cli->outbuf,smb_vwv0,0xFF); - SSVAL(cli->outbuf,smb_vwv2,fnum); - SIVAL(cli->outbuf,smb_vwv3,offset); - SSVAL(cli->outbuf,smb_vwv5,size); - SSVAL(cli->outbuf,smb_vwv6,size); - SSVAL(cli->outbuf,smb_vwv7,(size >> 16)); - SSVAL(cli->outbuf,smb_mid,cli->mid + i); - - if (bigoffset) { - SIVAL(cli->outbuf,smb_vwv10,(((SMB_BIG_UINT)offset)>>32) & 0xffffffff); - } - - return cli_send_smb(cli); + char **pbuf = (char **)priv; + memcpy(*pbuf, buf, n); + *pbuf += n; + return NT_STATUS_OK; } -/**************************************************************************** - Read size bytes at offset offset using SMBreadX. -****************************************************************************/ - -ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size) +ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, + off_t offset, size_t size) { - char *p; - size_t size2; - size_t readsize; - ssize_t total = 0; - /* We can only do direct reads if not signing or encrypting. */ - bool direct_reads = !client_is_signing_on(cli) && !cli_encryption_on(cli); - - if (size == 0) - return 0; - - /* - * Set readsize to the maximum size we can handle in one readX, - * rounded down to a multiple of 1024. - */ - - if (client_is_signing_on(cli) == false && - cli_encryption_on(cli) == false && - (cli->posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) { - readsize = CLI_SAMBA_MAX_POSIX_LARGE_READX_SIZE; - } else if (cli->capabilities & CAP_LARGE_READX) { - if (cli->is_samba) { - readsize = CLI_SAMBA_MAX_LARGE_READX_SIZE; - } else { - readsize = CLI_WINDOWS_MAX_LARGE_READX_SIZE; - } - } else { - readsize = (cli->max_xmit - (smb_size+32)) & ~1023; - } - - while (total < size) { - readsize = MIN(readsize, size-total); - - /* Issue a read and receive a reply */ - - if (!cli_issue_read(cli, fnum, offset, readsize, 0)) - return -1; - - if (direct_reads) { - if (!cli_receive_smb_readX_header(cli)) - return -1; - } else { - if (!cli_receive_smb(cli)) - return -1; - } - - /* Check for error. Make sure to check for DOS and NT - errors. */ - - if (cli_is_error(cli)) { - bool recoverable_error = False; - NTSTATUS status = NT_STATUS_OK; - uint8 eclass = 0; - uint32 ecode = 0; - - if (cli_is_nt_error(cli)) - status = cli_nt_error(cli); - else - cli_dos_error(cli, &eclass, &ecode); - - /* - * ERRDOS ERRmoredata or STATUS_MORE_ENRTIES is a - * recoverable error, plus we have valid data in the - * packet so don't error out here. - */ - - if ((eclass == ERRDOS && ecode == ERRmoredata) || - NT_STATUS_V(status) == NT_STATUS_V(STATUS_MORE_ENTRIES)) - recoverable_error = True; - - if (!recoverable_error) - return -1; - } - - /* size2 is the number of bytes the server returned. - * Might be zero. */ - size2 = SVAL(cli->inbuf, smb_vwv5); - size2 |= (((unsigned int)(SVAL(cli->inbuf, smb_vwv7))) << 16); - - if (size2 > readsize) { - DEBUG(5,("server returned more than we wanted!\n")); - return -1; - } else if (size2 < 0) { - DEBUG(5,("read return < 0!\n")); - return -1; - } - - if (size2) { - /* smb_vwv6 is the offset in the packet of the returned - * data bytes. Only valid if size2 != 0. */ - - if (!direct_reads) { - /* Copy data into buffer */ - p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6); - memcpy(buf + total, p, size2); - } else { - /* Ensure the remaining data matches the return size. */ - ssize_t toread = smb_len_large(cli->inbuf) - SVAL(cli->inbuf,smb_vwv6); - - /* Ensure the size is correct. */ - if (toread != size2) { - DEBUG(5,("direct read logic fail toread (%d) != size2 (%u)\n", - (int)toread, (unsigned int)size2 )); - return -1; - } - - /* Read data directly into buffer */ - toread = cli_receive_smb_data(cli,buf+total,size2); - if (toread != size2) { - DEBUG(5,("direct read read failure toread (%d) != size2 (%u)\n", - (int)toread, (unsigned int)size2 )); - return -1; - } - } - } - - total += size2; - offset += size2; - - /* - * If the server returned less than we asked for we're at EOF. - */ + NTSTATUS status; + ssize_t ret; - if (size2 < readsize) - break; + status = cli_pull(cli, fnum, offset, size, size, + cli_read_sink, &buf, &ret); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + return -1; } - - return total; + return ret; } #if 0 /* relies on client_receive_smb(), now a static in libsmb/clientgen.c */ -- cgit From bddceee09a12e6308b5e27bf666d8948b2a894d1 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 28 Feb 2008 23:15:11 +0100 Subject: Fix memleak in netsamlogon_cache_get(). Guenther (This used to be commit b736c77dc6c36dcdb601903fadf0ef7f163052a3) --- source3/libsmb/samlogon_cache.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/libsmb') diff --git a/source3/libsmb/samlogon_cache.c b/source3/libsmb/samlogon_cache.c index 0d855f4c6c..73b570c383 100644 --- a/source3/libsmb/samlogon_cache.c +++ b/source3/libsmb/samlogon_cache.c @@ -226,6 +226,7 @@ struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const DOM_SID * if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(0,("netsamlogon_cache_get: failed to pull entry from cache\n")); tdb_delete(netsamlogon_tdb, data); + TALLOC_FREE(info3); goto done; } -- cgit