diff options
author | Andrew Tridgell <tridge@samba.org> | 2008-12-16 11:41:20 +1100 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2008-12-16 11:41:20 +1100 |
commit | f448fde4e35e56508ad93be8de9f60d88e8b8dcd (patch) | |
tree | 597b58ba1af03f5250af918ec15300c385281706 /source3/libsmb | |
parent | a226d86dcec393b2cd657d5441c3041dfdf5cd8f (diff) | |
parent | 530758dc2a6dd6dce083789b328e16e51ba6573d (diff) | |
download | samba-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.c | 160 | ||||
-rw-r--r-- | source3/libsmb/cliconnect.c | 77 | ||||
-rw-r--r-- | source3/libsmb/clidfs.c | 17 | ||||
-rw-r--r-- | source3/libsmb/clientgen.c | 7 | ||||
-rw-r--r-- | source3/libsmb/clifile.c | 11 | ||||
-rw-r--r-- | source3/libsmb/clilist.c | 2 | ||||
-rw-r--r-- | source3/libsmb/clireadwrite.c | 30 | ||||
-rw-r--r-- | source3/libsmb/clitrans.c | 6 | ||||
-rw-r--r-- | source3/libsmb/dsgetdcname.c | 49 | ||||
-rw-r--r-- | source3/libsmb/libsmb_context.c | 18 | ||||
-rw-r--r-- | source3/libsmb/libsmb_dir.c | 11 | ||||
-rw-r--r-- | source3/libsmb/libsmb_server.c | 6 | ||||
-rw-r--r-- | source3/libsmb/namequery.c | 87 | ||||
-rw-r--r-- | source3/libsmb/namequery_dc.c | 4 | ||||
-rw-r--r-- | source3/libsmb/smb_seal.c | 7 |
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; |