summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/cliconnect.c63
-rw-r--r--source3/libsmb/clidfs.c13
-rw-r--r--source3/libsmb/clireadwrite.c19
-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/namequery.c77
7 files changed, 194 insertions, 56 deletions
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index d33775fbb8..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
@@ -863,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;
@@ -1221,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);
}
@@ -1252,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);
}
@@ -1495,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);
@@ -1643,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;
@@ -1774,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);
}
@@ -1783,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 35922b13e9..f0ac39fed0 100644
--- a/source3/libsmb/clidfs.c
+++ b/source3/libsmb/clidfs.c
@@ -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/clireadwrite.c b/source3/libsmb/clireadwrite.c
index ecf49396d1..1c2a0d56c4 100644
--- a/source3/libsmb/clireadwrite.c
+++ b/source3/libsmb/clireadwrite.c
@@ -109,6 +109,7 @@ 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;
@@ -136,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;
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/namequery.c b/source3/libsmb/namequery.c
index bcf849b795..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 );
@@ -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;