summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2008-12-16 11:41:20 +1100
committerAndrew Tridgell <tridge@samba.org>2008-12-16 11:41:20 +1100
commitf448fde4e35e56508ad93be8de9f60d88e8b8dcd (patch)
tree597b58ba1af03f5250af918ec15300c385281706 /source3/libsmb
parenta226d86dcec393b2cd657d5441c3041dfdf5cd8f (diff)
parent530758dc2a6dd6dce083789b328e16e51ba6573d (diff)
downloadsamba-f448fde4e35e56508ad93be8de9f60d88e8b8dcd.tar.gz
samba-f448fde4e35e56508ad93be8de9f60d88e8b8dcd.tar.bz2
samba-f448fde4e35e56508ad93be8de9f60d88e8b8dcd.zip
Merge branch 'master' of ssh://git.samba.org/data/git/samba
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/async_smb.c160
-rw-r--r--source3/libsmb/cliconnect.c77
-rw-r--r--source3/libsmb/clidfs.c17
-rw-r--r--source3/libsmb/clientgen.c7
-rw-r--r--source3/libsmb/clifile.c11
-rw-r--r--source3/libsmb/clilist.c2
-rw-r--r--source3/libsmb/clireadwrite.c30
-rw-r--r--source3/libsmb/clitrans.c6
-rw-r--r--source3/libsmb/dsgetdcname.c49
-rw-r--r--source3/libsmb/libsmb_context.c18
-rw-r--r--source3/libsmb/libsmb_dir.c11
-rw-r--r--source3/libsmb/libsmb_server.c6
-rw-r--r--source3/libsmb/namequery.c87
-rw-r--r--source3/libsmb/namequery_dc.c4
-rw-r--r--source3/libsmb/smb_seal.c7
15 files changed, 345 insertions, 147 deletions
diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c
index d371e057e3..fd2fe930f8 100644
--- a/source3/libsmb/async_smb.c
+++ b/source3/libsmb/async_smb.c
@@ -218,6 +218,118 @@ static bool find_andx_cmd_ofs(char *buf, size_t *pofs)
}
/**
+ * @brief Do the smb chaining at a buffer level
+ * @param[in] poutbuf Pointer to the talloc'ed buffer to be modified
+ * @param[in] smb_command The command that we want to issue
+ * @param[in] wct How many words?
+ * @param[in] vwv The words, already in network order
+ * @param[in] bytes_alignment How shall we align "bytes"?
+ * @param[in] num_bytes How many bytes?
+ * @param[in] bytes The data the request ships
+ *
+ * smb_splice_chain() adds the vwv and bytes to the request already present in
+ * *poutbuf.
+ */
+
+bool smb_splice_chain(char **poutbuf, uint8_t smb_command,
+ uint8_t wct, const uint16_t *vwv,
+ size_t bytes_alignment,
+ uint16_t num_bytes, const uint8_t *bytes)
+{
+ char *outbuf;
+ size_t old_size, new_size;
+ size_t ofs;
+ size_t chain_padding = 0;
+ size_t bytes_padding = 0;
+ bool first_request;
+
+ old_size = talloc_get_size(*poutbuf);
+
+ /*
+ * old_size == smb_wct means we're pushing the first request in for
+ * libsmb/
+ */
+
+ first_request = (old_size == smb_wct);
+
+ if (!first_request && ((old_size % 4) != 0)) {
+ /*
+ * Align the wct field of subsequent requests to a 4-byte
+ * boundary
+ */
+ chain_padding = 4 - (old_size % 4);
+ }
+
+ /*
+ * After the old request comes the new wct field (1 byte), the vwv's
+ * and the num_bytes field. After at we might need to align the bytes
+ * given to us to "bytes_alignment", increasing the num_bytes value.
+ */
+
+ new_size = old_size + chain_padding + 1 + wct * sizeof(uint16_t) + 2;
+
+ if ((bytes_alignment != 0) && ((new_size % bytes_alignment) != 0)) {
+ bytes_padding = bytes_alignment + (new_size % bytes_alignment);
+ }
+
+ new_size += bytes_padding + num_bytes;
+
+ if (new_size > 0xffff) {
+ DEBUG(1, ("splice_chain: %u bytes won't fit\n",
+ (unsigned)new_size));
+ return false;
+ }
+
+ outbuf = TALLOC_REALLOC_ARRAY(NULL, *poutbuf, char, new_size);
+ if (outbuf == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ return false;
+ }
+ *poutbuf = outbuf;
+
+ if (first_request) {
+ SCVAL(outbuf, smb_com, smb_command);
+ } else {
+ size_t andx_cmd_ofs;
+
+ if (!find_andx_cmd_ofs(outbuf, &andx_cmd_ofs)) {
+ DEBUG(1, ("invalid command chain\n"));
+ *poutbuf = TALLOC_REALLOC_ARRAY(
+ NULL, *poutbuf, char, old_size);
+ return false;
+ }
+
+ if (chain_padding != 0) {
+ memset(outbuf + old_size, 0, chain_padding);
+ old_size += chain_padding;
+ }
+
+ SCVAL(outbuf, andx_cmd_ofs, smb_command);
+ SSVAL(outbuf, andx_cmd_ofs + 2, old_size - 4);
+ }
+
+ ofs = old_size;
+
+ SCVAL(outbuf, ofs, wct);
+ ofs += 1;
+
+ memcpy(outbuf + ofs, vwv, sizeof(uint16_t) * wct);
+ ofs += sizeof(uint16_t) * wct;
+
+ SSVAL(outbuf, ofs, num_bytes + bytes_padding);
+ ofs += sizeof(uint16_t);
+
+ if (bytes_padding != 0) {
+ memset(outbuf + ofs, 0, bytes_padding);
+ ofs += bytes_padding;
+ }
+
+ memcpy(outbuf + ofs, bytes, num_bytes);
+
+ return true;
+}
+
+/**
* @brief Destroy an async_req that is the visible part of a cli_request
* @param[in] req The request to kill
* @retval Return 0 to make talloc happy
@@ -286,10 +398,7 @@ static struct async_req *cli_request_chain(TALLOC_CTX *mem_ctx,
const uint8_t *bytes)
{
struct async_req **tmp_reqs;
- char *tmp_buf;
struct cli_request *req;
- size_t old_size, new_size;
- size_t ofs;
req = cli->chain_accumulator;
@@ -313,52 +422,11 @@ static struct async_req *cli_request_chain(TALLOC_CTX *mem_ctx,
talloc_set_destructor(req->async[req->num_async-1],
cli_async_req_destructor);
- old_size = talloc_get_size(req->outbuf);
-
- /*
- * We need space for the wct field, the words, the byte count field
- * and the bytes themselves.
- */
- new_size = old_size + 1 + wct * sizeof(uint16_t) + 2 + num_bytes;
-
- if (new_size > 0xffff) {
- DEBUG(1, ("cli_request_chain: %u bytes won't fit\n",
- (unsigned)new_size));
+ if (!smb_splice_chain(&req->outbuf, smb_command, wct, vwv,
+ 0, num_bytes, bytes)) {
goto fail;
}
- tmp_buf = TALLOC_REALLOC_ARRAY(NULL, req->outbuf, char, new_size);
- if (tmp_buf == NULL) {
- DEBUG(0, ("talloc failed\n"));
- goto fail;
- }
- req->outbuf = tmp_buf;
-
- if (old_size == smb_wct) {
- SCVAL(req->outbuf, smb_com, smb_command);
- } else {
- size_t andx_cmd_ofs;
- if (!find_andx_cmd_ofs(req->outbuf, &andx_cmd_ofs)) {
- DEBUG(1, ("invalid command chain\n"));
- goto fail;
- }
- SCVAL(req->outbuf, andx_cmd_ofs, smb_command);
- SSVAL(req->outbuf, andx_cmd_ofs + 2, old_size - 4);
- }
-
- ofs = old_size;
-
- SCVAL(req->outbuf, ofs, wct);
- ofs += 1;
-
- memcpy(req->outbuf + ofs, vwv, sizeof(uint16_t) * wct);
- ofs += sizeof(uint16_t) * wct;
-
- SSVAL(req->outbuf, ofs, num_bytes);
- ofs += sizeof(uint16_t);
-
- memcpy(req->outbuf + ofs, bytes, num_bytes);
-
return req->async[req->num_async-1];
fail:
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 8b7ac7d718..125345fccb 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -22,22 +22,21 @@
static const struct {
int prot;
- const char *name;
-} prots[] = {
- {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
- {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
- {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
- {PROTOCOL_LANMAN1,"LANMAN1.0"},
- {PROTOCOL_LANMAN2,"LM1.2X002"},
- {PROTOCOL_LANMAN2,"DOS LANMAN2.1"},
- {PROTOCOL_LANMAN2,"LANMAN2.1"},
- {PROTOCOL_LANMAN2,"Samba"},
- {PROTOCOL_NT1,"NT LANMAN 1.0"},
- {PROTOCOL_NT1,"NT LM 0.12"},
- {-1,NULL}
+ const char name[24];
+} prots[10] = {
+ {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
+ {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
+ {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
+ {PROTOCOL_LANMAN1, "LANMAN1.0"},
+ {PROTOCOL_LANMAN2, "LM1.2X002"},
+ {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
+ {PROTOCOL_LANMAN2, "LANMAN2.1"},
+ {PROTOCOL_LANMAN2, "Samba"},
+ {PROTOCOL_NT1, "NT LANMAN 1.0"},
+ {PROTOCOL_NT1, "NT LM 0.12"},
};
-static const char *star_smbserver_name = "*SMBSERVER";
+#define STAR_SMBSERVER "*SMBSERVER"
/**
* Set the user session key for a connection
@@ -748,19 +747,11 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use
if (NT_STATUS_IS_OK(nt_status)) {
- DATA_BLOB key = data_blob(ntlmssp_state->session_key.data,
- ntlmssp_state->session_key.length);
- DATA_BLOB null_blob = data_blob_null;
- bool res;
-
fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
cli_set_session_key(cli, ntlmssp_state->session_key);
- res = cli_simple_set_signing(cli, key, null_blob);
-
- data_blob_free(&key);
-
- if (res) {
+ if (cli_simple_set_signing(
+ cli, ntlmssp_state->session_key, data_blob_null)) {
/* 'resign' the last message, so we get the right sequence numbers
for checking the first reply from the server */
@@ -871,7 +862,7 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
if (principal == NULL &&
!is_ipaddress(cli->desthost) &&
- !strequal(star_smbserver_name,
+ !strequal(STAR_SMBSERVER,
cli->desthost)) {
char *realm = NULL;
char *machine = NULL;
@@ -1229,9 +1220,10 @@ void cli_negprot_send(struct cli_state *cli)
cli_set_message(cli->outbuf,0,0,True);
p = smb_buf(cli->outbuf);
- for (numprots=0;
- prots[numprots].name && prots[numprots].prot<=cli->protocol;
- numprots++) {
+ for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
+ if (prots[numprots].prot > cli->protocol) {
+ break;
+ }
*p++ = 2;
p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
}
@@ -1260,18 +1252,23 @@ bool cli_negprot(struct cli_state *cli)
memset(cli->outbuf,'\0',smb_size);
+ plength = 0;
+
/* setup the protocol strings */
- for (plength=0,numprots=0;
- prots[numprots].name && prots[numprots].prot<=cli->protocol;
- numprots++)
+ for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
+ if (prots[numprots].prot > cli->protocol) {
+ break;
+ }
plength += strlen(prots[numprots].name)+2;
+ }
cli_set_message(cli->outbuf,0,plength,True);
p = smb_buf(cli->outbuf);
- for (numprots=0;
- prots[numprots].name && prots[numprots].prot<=cli->protocol;
- numprots++) {
+ for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
+ if (prots[numprots].prot > cli->protocol) {
+ break;
+ }
*p++ = 2;
p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
}
@@ -1503,7 +1500,7 @@ NTSTATUS cli_connect(struct cli_state *cli,
/* reasonable default hostname */
if (!host) {
- host = star_smbserver_name;
+ host = STAR_SMBSERVER;
}
fstrcpy(cli->desthost, host);
@@ -1623,7 +1620,7 @@ NTSTATUS cli_start_connection(struct cli_state **output_cli,
if (dest_ss) {
ss = *dest_ss;
} else {
- zero_addr(&ss);
+ zero_sockaddr(&ss);
}
again:
@@ -1651,8 +1648,8 @@ again:
*p = 0;
goto again;
}
- if (strcmp(called.name, star_smbserver_name)) {
- make_nmb_name(&called , star_smbserver_name, 0x20);
+ if (strcmp(called.name, STAR_SMBSERVER)) {
+ make_nmb_name(&called , STAR_SMBSERVER, 0x20);
goto again;
}
return NT_STATUS_BAD_NETWORK_NAME;
@@ -1782,7 +1779,7 @@ bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srcho
*/
if(is_ipaddress(desthost)) {
- make_nmb_name(&called, star_smbserver_name, 0x20);
+ make_nmb_name(&called, STAR_SMBSERVER, 0x20);
} else {
make_nmb_name(&called, desthost, 0x20);
}
@@ -1791,7 +1788,7 @@ bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srcho
NTSTATUS status;
struct nmb_name smbservername;
- make_nmb_name(&smbservername, star_smbserver_name, 0x20);
+ make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
/*
* If the name wasn't *SMBSERVER then
diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c
index 7b63f9535e..f0ac39fed0 100644
--- a/source3/libsmb/clidfs.c
+++ b/source3/libsmb/clidfs.c
@@ -144,13 +144,13 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
server_n = server;
- zero_addr(&ss);
+ zero_sockaddr(&ss);
make_nmb_name(&calling, global_myname(), 0x0);
make_nmb_name(&called , server, name_type);
again:
- zero_addr(&ss);
+ zero_sockaddr(&ss);
if (have_ip)
ss = dest_ss;
@@ -471,18 +471,19 @@ static void cm_set_password(const char *newpass)
/****************************************************************************
****************************************************************************/
-void cli_cm_set_credentials(void)
+void cli_cm_set_credentials(struct user_auth_info *auth_info)
{
SAFE_FREE(cm_creds.username);
- cm_creds.username = SMB_STRDUP(get_cmdline_auth_info_username());
+ cm_creds.username = SMB_STRDUP(get_cmdline_auth_info_username(
+ auth_info));
- if (get_cmdline_auth_info_got_pass()) {
- cm_set_password(get_cmdline_auth_info_password());
+ if (get_cmdline_auth_info_got_pass(auth_info)) {
+ cm_set_password(get_cmdline_auth_info_password(auth_info));
}
- cm_creds.use_kerberos = get_cmdline_auth_info_use_kerberos();
+ cm_creds.use_kerberos = get_cmdline_auth_info_use_kerberos(auth_info);
cm_creds.fallback_after_kerberos = false;
- cm_creds.signing_state = get_cmdline_auth_info_signing_state();
+ cm_creds.signing_state = get_cmdline_auth_info_signing_state(auth_info);
}
/****************************************************************************
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index 8a5aedfde5..d94427809c 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -732,12 +732,7 @@ struct async_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
NTSTATUS cli_echo_recv(struct async_req *req)
{
- SMB_ASSERT(req->state >= ASYNC_REQ_DONE);
- if (req->state == ASYNC_REQ_ERROR) {
- return req->status;
- }
-
- return NT_STATUS_OK;
+ return async_req_simple_recv(req);
}
/**
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index a9e81082ea..733abb6510 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -908,9 +908,8 @@ NTSTATUS cli_open_recv(struct async_req *req, int *fnum)
uint8_t *bytes;
NTSTATUS status;
- SMB_ASSERT(req->state >= ASYNC_REQ_DONE);
- if (req->state == ASYNC_REQ_ERROR) {
- return req->status;
+ if (async_req_is_error(req, &status)) {
+ return status;
}
status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
@@ -985,10 +984,10 @@ NTSTATUS cli_close_recv(struct async_req *req)
uint16_t *vwv;
uint16_t num_bytes;
uint8_t *bytes;
+ NTSTATUS status;
- SMB_ASSERT(req->state >= ASYNC_REQ_DONE);
- if (req->state == ASYNC_REQ_ERROR) {
- return req->status;
+ if (async_req_is_error(req, &status)) {
+ return status;
}
return cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c
index 50918458b0..cebafc6919 100644
--- a/source3/libsmb/clilist.c
+++ b/source3/libsmb/clilist.c
@@ -417,7 +417,7 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
}
SAFE_FREE(mask);
- if (ff_searchcount > 0) {
+ if (ff_searchcount > 0 && ff_eos == 0 && finfo.name) {
mask = SMB_STRDUP(finfo.name);
} else {
mask = SMB_STRDUP("");
diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c
index cc982683d0..1c2a0d56c4 100644
--- a/source3/libsmb/clireadwrite.c
+++ b/source3/libsmb/clireadwrite.c
@@ -109,12 +109,12 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received,
uint16_t *vwv;
uint16_t num_bytes;
uint8_t *bytes;
+ uint8_t *buf;
NTSTATUS status;
size_t size;
- SMB_ASSERT(req->state >= ASYNC_REQ_DONE);
- if (req->state == ASYNC_REQ_ERROR) {
- return req->status;
+ if (async_req_is_error(req, &status)) {
+ return status;
}
status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
@@ -137,6 +137,24 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received,
return NT_STATUS_UNEXPECTED_IO_ERROR;
}
+ /*
+ * bcc field must be valid for small reads, for large reads the 16-bit
+ * bcc field can't be correct.
+ */
+
+ if ((size < 0xffff) && (size > num_bytes)) {
+ DEBUG(5, ("server announced more bytes than sent\n"));
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+
+ buf = (uint8_t *)smb_base(cli_req->inbuf) + SVAL(vwv+6, 0);
+
+ if (trans_oob(smb_len(cli_req->inbuf), SVAL(vwv+6, 0), size)
+ || (buf < bytes)) {
+ DEBUG(5, ("server returned invalid read&x data offset\n"));
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+
*rcvbuf = (uint8_t *)(smb_base(cli_req->inbuf) + SVAL(vwv + 6, 0));
*received = size;
return NT_STATUS_OK;
@@ -405,10 +423,10 @@ NTSTATUS cli_pull_recv(struct async_req *req, SMB_OFF_T *received)
{
struct cli_pull_state *state = talloc_get_type_abort(
req->private_data, struct cli_pull_state);
+ NTSTATUS status;
- SMB_ASSERT(req->state >= ASYNC_REQ_DONE);
- if (req->state == ASYNC_REQ_ERROR) {
- return req->status;
+ if (async_req_is_error(req, &status)) {
+ return status;
}
*received = state->pushed;
return NT_STATUS_OK;
diff --git a/source3/libsmb/clitrans.c b/source3/libsmb/clitrans.c
index bbdfb75fcd..120b6c0e29 100644
--- a/source3/libsmb/clitrans.c
+++ b/source3/libsmb/clitrans.c
@@ -1316,10 +1316,10 @@ NTSTATUS cli_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
req->private_data, struct cli_request);
struct cli_trans_state *state = talloc_get_type_abort(
cli_req->recv_helper.priv, struct cli_trans_state);
+ NTSTATUS status;
- SMB_ASSERT(req->state >= ASYNC_REQ_DONE);
- if (req->state == ASYNC_REQ_ERROR) {
- return req->status;
+ if (async_req_is_error(req, &status)) {
+ return status;
}
if (setup != NULL) {
diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c
index d8c2b70175..3491544175 100644
--- a/source3/libsmb/dsgetdcname.c
+++ b/source3/libsmb/dsgetdcname.c
@@ -1119,6 +1119,27 @@ static NTSTATUS dsgetdcname_rediscover(TALLOC_CTX *mem_ctx,
num_dcs, info);
}
+static bool is_closest_site(struct netr_DsRGetDCNameInfo *info)
+{
+ if (info->dc_flags & DS_SERVER_CLOSEST) {
+ return true;
+ }
+
+ if (!info->client_site_name) {
+ return true;
+ }
+
+ if (!info->dc_site_name) {
+ return false;
+ }
+
+ if (strcmp(info->client_site_name, info->dc_site_name) == 0) {
+ return true;
+ }
+
+ return false;
+}
+
/********************************************************************
dsgetdcname.
@@ -1136,6 +1157,8 @@ NTSTATUS dsgetdcname(TALLOC_CTX *mem_ctx,
NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
struct netr_DsRGetDCNameInfo *myinfo = NULL;
char *query_site = NULL;
+ bool first = true;
+ struct netr_DsRGetDCNameInfo *first_info = NULL;
DEBUG(10,("dsgetdcname: domain_name: %s, "
"domain_guid: %s, site_name: %s, flags: 0x%08x\n",
@@ -1163,7 +1186,6 @@ NTSTATUS dsgetdcname(TALLOC_CTX *mem_ctx,
status = dsgetdcname_cached(mem_ctx, msg_ctx, domain_name, domain_guid,
flags, query_site, &myinfo);
if (NT_STATUS_IS_OK(status)) {
- *info = myinfo;
goto done;
}
@@ -1176,12 +1198,27 @@ NTSTATUS dsgetdcname(TALLOC_CTX *mem_ctx,
domain_guid, flags, query_site,
&myinfo);
- if (NT_STATUS_IS_OK(status)) {
- *info = myinfo;
- }
-
done:
SAFE_FREE(query_site);
- return status;
+ if (!NT_STATUS_IS_OK(status)) {
+ if (!first) {
+ *info = first_info;
+ return NT_STATUS_OK;
+ }
+ return status;
+ }
+
+ if (!first) {
+ TALLOC_FREE(first_info);
+ } else if (!is_closest_site(myinfo)) {
+ first = false;
+ first_info = myinfo;
+ /* TODO: may use the next_closest_site here */
+ query_site = SMB_STRDUP(myinfo->client_site_name);
+ goto rediscover;
+ }
+
+ *info = myinfo;
+ return NT_STATUS_OK;
}
diff --git a/source3/libsmb/libsmb_context.c b/source3/libsmb/libsmb_context.c
index 19843383de..becee17f65 100644
--- a/source3/libsmb/libsmb_context.c
+++ b/source3/libsmb/libsmb_context.c
@@ -633,13 +633,19 @@ smbc_set_credentials(char *workgroup,
smbc_bool use_kerberos,
char *signing_state)
{
-
- set_cmdline_auth_info_username(user);
- set_cmdline_auth_info_password(password);
- set_cmdline_auth_info_use_kerberos(use_kerberos);
- if (! set_cmdline_auth_info_signing_state(signing_state)) {
+ struct user_auth_info *auth_info;
+
+ auth_info = user_auth_info_init(talloc_tos());
+ if (auth_info == NULL) {
+ return;
+ }
+ set_cmdline_auth_info_username(auth_info, user);
+ set_cmdline_auth_info_password(auth_info, password);
+ set_cmdline_auth_info_use_kerberos(auth_info, use_kerberos);
+ if (! set_cmdline_auth_info_signing_state(auth_info, signing_state)) {
DEBUG(0, ("Invalid signing state: %s", signing_state));
}
set_global_myworkgroup(workgroup);
- cli_cm_set_credentials();
+ cli_cm_set_credentials(auth_info);
+ TALLOC_FREE(auth_info);
}
diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c
index aa313f2c05..d12e7487f6 100644
--- a/source3/libsmb/libsmb_dir.c
+++ b/source3/libsmb/libsmb_dir.c
@@ -1193,8 +1193,6 @@ SMBC_mkdir_ctx(SMBCCTX *context,
* Our list function simply checks to see if a directory is not empty
*/
-static int smbc_rmdir_dirempty = True;
-
static void
rmdir_list_fn(const char *mnt,
file_info *finfo,
@@ -1203,7 +1201,8 @@ rmdir_list_fn(const char *mnt,
{
if (strncmp(finfo->name, ".", 1) != 0 &&
strncmp(finfo->name, "..", 2) != 0) {
- smbc_rmdir_dirempty = False;
+ bool *smbc_rmdir_dirempty = (bool *)state;
+ *smbc_rmdir_dirempty = false;
}
}
@@ -1292,8 +1291,7 @@ SMBC_rmdir_ctx(SMBCCTX *context,
/* Local storage to avoid buffer overflows */
char *lpath;
-
- smbc_rmdir_dirempty = True; /* Make this so ... */
+ bool smbc_rmdir_dirempty = true;
lpath = talloc_asprintf(frame, "%s\\*",
targetpath);
@@ -1305,7 +1303,8 @@ SMBC_rmdir_ctx(SMBCCTX *context,
if (cli_list(targetcli, lpath,
aDIR | aSYSTEM | aHIDDEN,
- rmdir_list_fn, NULL) < 0) {
+ rmdir_list_fn,
+ &smbc_rmdir_dirempty) < 0) {
/* Fix errno to ignore latest error ... */
DEBUG(5, ("smbc_rmdir: "
diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c
index aeec255350..5e37871deb 100644
--- a/source3/libsmb/libsmb_server.c
+++ b/source3/libsmb/libsmb_server.c
@@ -248,7 +248,7 @@ SMBC_server(TALLOC_CTX *ctx,
const char *username_used;
NTSTATUS status;
- zero_addr(&ss);
+ zero_sockaddr(&ss);
ZERO_STRUCT(c);
if (server[0] == 0) {
@@ -348,7 +348,7 @@ SMBC_server(TALLOC_CTX *ctx,
again:
- zero_addr(&ss);
+ zero_sockaddr(&ss);
/* have to open a new connection */
if ((c = cli_initialise()) == NULL) {
@@ -595,7 +595,7 @@ SMBC_attr_server(TALLOC_CTX *ctx,
flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
}
- zero_addr(&ss);
+ zero_sockaddr(&ss);
nt_status = cli_full_connection(&ipc_cli,
global_myname(), server,
&ss, 0, "IPC$", "?????",
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index e6eed8289e..05679570d4 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -34,6 +34,8 @@ bool global_in_nmbd = False;
****************************************************************************/
#define SAFKEY_FMT "SAF/DOMAIN/%s"
#define SAF_TTL 900
+#define SAFJOINKEY_FMT "SAFJOIN/DOMAIN/%s"
+#define SAFJOIN_TTL 3600
static char *saf_key(const char *domain)
{
@@ -44,6 +46,15 @@ static char *saf_key(const char *domain)
return keystr;
}
+static char *saf_join_key(const char *domain)
+{
+ char *keystr;
+
+ asprintf_strupper_m(&keystr, SAFJOINKEY_FMT, domain);
+
+ return keystr;
+}
+
/****************************************************************************
****************************************************************************/
@@ -69,7 +80,7 @@ bool saf_store( const char *domain, const char *servername )
return False;
key = saf_key( domain );
- expire = time( NULL ) + SAF_TTL;
+ expire = time( NULL ) + lp_parm_int(-1, "saf","ttl", SAF_TTL);
DEBUG(10,("saf_store: domain = [%s], server = [%s], expire = [%u]\n",
domain, servername, (unsigned int)expire ));
@@ -81,6 +92,38 @@ bool saf_store( const char *domain, const char *servername )
return ret;
}
+bool saf_join_store( const char *domain, const char *servername )
+{
+ char *key;
+ time_t expire;
+ bool ret = False;
+
+ if ( !domain || !servername ) {
+ DEBUG(2,("saf_join_store: Refusing to store empty domain or servername!\n"));
+ return False;
+ }
+
+ if ( (strlen(domain) == 0) || (strlen(servername) == 0) ) {
+ DEBUG(0,("saf_join_store: refusing to store 0 length domain or servername!\n"));
+ return False;
+ }
+
+ if ( !gencache_init() )
+ return False;
+
+ key = saf_join_key( domain );
+ expire = time( NULL ) + lp_parm_int(-1, "saf","join ttl", SAFJOIN_TTL);
+
+ DEBUG(10,("saf_join_store: domain = [%s], server = [%s], expire = [%u]\n",
+ domain, servername, (unsigned int)expire ));
+
+ ret = gencache_set( key, servername, expire );
+
+ SAFE_FREE( key );
+
+ return ret;
+}
+
bool saf_delete( const char *domain )
{
char *key;
@@ -94,15 +137,22 @@ bool saf_delete( const char *domain )
if ( !gencache_init() )
return False;
+ key = saf_join_key(domain);
+ ret = gencache_del(key);
+ SAFE_FREE(key);
+
+ if (ret) {
+ DEBUG(10,("saf_delete[join]: domain = [%s]\n", domain ));
+ }
+
key = saf_key(domain);
ret = gencache_del(key);
+ SAFE_FREE(key);
if (ret) {
DEBUG(10,("saf_delete: domain = [%s]\n", domain ));
}
- SAFE_FREE( key );
-
return ret;
}
@@ -124,6 +174,18 @@ char *saf_fetch( const char *domain )
if ( !gencache_init() )
return False;
+ key = saf_join_key( domain );
+
+ ret = gencache_get( key, &server, &timeout );
+
+ SAFE_FREE( key );
+
+ if ( ret ) {
+ DEBUG(5,("saf_fetch[join]: Returning \"%s\" for \"%s\" domain\n",
+ server, domain ));
+ return server;
+ }
+
key = saf_key( domain );
ret = gencache_get( key, &server, &timeout );
@@ -331,7 +393,7 @@ bool name_status_find(const char *q_name,
if (!interpret_string_addr(&ss, lp_socket_address(),
AI_NUMERICHOST|AI_PASSIVE)) {
- zero_addr(&ss);
+ zero_sockaddr(&ss);
}
sock = open_socket_in(SOCK_DGRAM, 0, 3, &ss, True);
@@ -526,9 +588,9 @@ static int remove_duplicate_addrs2(struct ip_service *iplist, int count )
}
for ( j=i+1; j<count; j++ ) {
- if (addr_equal((struct sockaddr *)&iplist[i].ss, (struct sockaddr *)&iplist[j].ss) &&
+ if (sockaddr_equal((struct sockaddr *)&iplist[i].ss, (struct sockaddr *)&iplist[j].ss) &&
iplist[i].port == iplist[j].port) {
- zero_addr(&iplist[j].ss);
+ zero_sockaddr(&iplist[j].ss);
}
}
}
@@ -954,7 +1016,7 @@ NTSTATUS name_resolve_bcast(const char *name,
if (!interpret_string_addr(&ss, lp_socket_address(),
AI_NUMERICHOST|AI_PASSIVE)) {
- zero_addr(&ss);
+ zero_sockaddr(&ss);
}
sock = open_socket_in( SOCK_DGRAM, 0, 3, &ss, true );
@@ -1042,7 +1104,7 @@ NTSTATUS resolve_wins(const char *name,
/* the address we will be sending from */
if (!interpret_string_addr(&src_ss, lp_socket_address(),
AI_NUMERICHOST|AI_PASSIVE)) {
- zero_addr(&src_ss);
+ zero_sockaddr(&src_ss);
}
if (src_ss.ss_family != AF_INET) {
@@ -2098,6 +2160,15 @@ NTSTATUS get_sorted_dc_list( const char *domain,
status = get_dc_list(domain, sitename, ip_list,
count, lookup_type, &ordered);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NO_LOGON_SERVERS)
+ && sitename) {
+ DEBUG(3,("get_sorted_dc_list: no server for name %s available"
+ " in site %s, fallback to all servers\n",
+ domain, sitename));
+ status = get_dc_list(domain, NULL, ip_list,
+ count, lookup_type, &ordered);
+ }
+
if (!NT_STATUS_IS_OK(status)) {
SAFE_FREE(*ip_list);
*count = 0;
diff --git a/source3/libsmb/namequery_dc.c b/source3/libsmb/namequery_dc.c
index 306f720a02..7b0748f86b 100644
--- a/source3/libsmb/namequery_dc.c
+++ b/source3/libsmb/namequery_dc.c
@@ -134,7 +134,7 @@ static bool ads_dc_name(const char *domain,
#ifdef HAVE_ADS
*dc_ss = ads->ldap.ss;
#else
- zero_addr(dc_ss);
+ zero_sockaddr(dc_ss);
#endif
ads_destroy(&ads);
@@ -217,7 +217,7 @@ bool get_dc_name(const char *domain,
bool ret;
bool our_domain = False;
- zero_addr(&dc_ss);
+ zero_sockaddr(&dc_ss);
ret = False;
diff --git a/source3/libsmb/smb_seal.c b/source3/libsmb/smb_seal.c
index a81ae9afd5..795c8bc14c 100644
--- a/source3/libsmb/smb_seal.c
+++ b/source3/libsmb/smb_seal.c
@@ -388,10 +388,17 @@ void common_free_encryption_state(struct smb_trans_enc_state **pp_es)
void common_free_enc_buffer(struct smb_trans_enc_state *es, char *buf)
{
+ uint16_t enc_ctx_num;
+
if (!common_encryption_on(es)) {
return;
}
+ if (!NT_STATUS_IS_OK(get_enc_ctx_num((const uint8_t *)buf,
+ &enc_ctx_num))) {
+ return;
+ }
+
if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
SAFE_FREE(buf);
return;