summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/auth/auth_domain.c7
-rw-r--r--source3/auth/token_util.c2
-rw-r--r--source3/client/mount.cifs.c71
-rw-r--r--source3/configure.in4
-rw-r--r--source3/include/smb.h10
-rw-r--r--source3/libsmb/clidgram.c6
-rw-r--r--source3/nmbd/nmbd_packets.c6
-rw-r--r--source3/pam_smbpass/support.c8
-rw-r--r--source3/passdb/lookup_sid.c45
-rw-r--r--source3/passdb/passdb.c85
-rw-r--r--source3/passdb/secrets.c67
-rw-r--r--source3/rpc_client/cli_pipe.c126
-rw-r--r--source3/rpc_server/srv_lsa_nt.c37
-rw-r--r--source3/winbindd/winbindd_cm.c145
14 files changed, 384 insertions, 235 deletions
diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c
index 7cddabbbbd..b2c87174fd 100644
--- a/source3/auth/auth_domain.c
+++ b/source3/auth/auth_domain.c
@@ -127,8 +127,11 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result)));
uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
uint32 sec_chan_type = 0;
unsigned char machine_pwd[16];
+ const char *account_name;
- if (!get_trust_pw(domain, machine_pwd, &sec_chan_type)) {
+ if (!get_trust_pw_hash(domain, machine_pwd, &account_name,
+ &sec_chan_type))
+ {
DEBUG(0, ("connect_to_domain_password_server: could not fetch "
"trust account password for domain '%s'\n",
domain));
@@ -142,7 +145,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result)));
dc_name, /* server name */
domain, /* domain */
global_myname(), /* client name */
- global_myname(), /* machine account name */
+ account_name, /* machine account name */
machine_pwd,
sec_chan_type,
&neg_flags);
diff --git a/source3/auth/token_util.c b/source3/auth/token_util.c
index 63672bcf74..330acde6e4 100644
--- a/source3/auth/token_util.c
+++ b/source3/auth/token_util.c
@@ -85,7 +85,7 @@ NT_USER_TOKEN *get_root_nt_token( void )
return token;
if ( !(pw = sys_getpwnam( "root" )) ) {
- DEBUG(0,("get_root_nt_token: getpwnam\"root\") failed!\n"));
+ DEBUG(0,("get_root_nt_token: getpwnam(\"root\") failed!\n"));
return NULL;
}
diff --git a/source3/client/mount.cifs.c b/source3/client/mount.cifs.c
index f141e8e4c7..ec245ed200 100644
--- a/source3/client/mount.cifs.c
+++ b/source3/client/mount.cifs.c
@@ -354,6 +354,8 @@ static int parse_options(char ** optionsp, int * filesys_flags)
int out_len = 0;
int word_len;
int rc = 0;
+ char user[32];
+ char group[32];
if (!optionsp || !*optionsp)
return 1;
@@ -364,6 +366,13 @@ static int parse_options(char ** optionsp, int * filesys_flags)
/* BB fixme check for separator override BB */
+ if (getuid()) {
+ got_uid = 1;
+ snprintf(user,sizeof(user),"%u",getuid());
+ got_gid = 1;
+ snprintf(group,sizeof(group),"%u",getgid());
+ }
+
/* while ((data = strsep(&options, ",")) != NULL) { */
while(data != NULL) {
/* check if ends with trailing comma */
@@ -526,33 +535,33 @@ static int parse_options(char ** optionsp, int * filesys_flags)
got_uid = 1;
if (!isdigit(*value)) {
struct passwd *pw;
- static char temp[32];
if (!(pw = getpwnam(value))) {
printf("bad user name \"%s\"\n", value);
exit(1);
}
- snprintf(temp, sizeof(temp), "%u", pw->pw_uid);
- value = temp;
- endpwent();
+ snprintf(user, sizeof(user), "%u", pw->pw_uid);
+ } else {
+ strlcpy(user,value,sizeof(user));
}
}
+ goto nocopy;
} else if (strncmp(data, "gid", 3) == 0) {
if (value && *value) {
got_gid = 1;
if (!isdigit(*value)) {
struct group *gr;
- static char temp[32];
if (!(gr = getgrnam(value))) {
printf("bad group name \"%s\"\n", value);
exit(1);
}
- snprintf(temp, sizeof(temp), "%u", gr->gr_gid);
- value = temp;
- endpwent();
+ snprintf(group, sizeof(group), "%u", gr->gr_gid);
+ } else {
+ strlcpy(group,value,sizeof(group));
}
}
+ goto nocopy;
/* fmask and dmask synonyms for people used to smbfs syntax */
} else if (strcmp(data, "file_mode") == 0 || strcmp(data, "fmask")==0) {
if (!value || !*value) {
@@ -643,17 +652,55 @@ static int parse_options(char ** optionsp, int * filesys_flags)
exit(1);
}
- if (out_len)
- out[out_len++] = ',';
+ if (out_len) {
+ strlcat(out, ",", out_len + word_len + 2);
+ out_len++;
+ }
+
if (value)
- snprintf(out + out_len, word_len + 2, "%s=%s", data, value);
+ snprintf(out + out_len, word_len + 1, "%s=%s", data, value);
else
- snprintf(out + out_len, word_len + 2, "%s", data);
+ snprintf(out + out_len, word_len + 1, "%s", data);
out_len = strlen(out);
nocopy:
data = next_keyword;
}
+
+ /* special-case the uid and gid */
+ if (got_uid) {
+ word_len = strlen(user);
+
+ out = (char *)realloc(out, out_len + word_len + 6);
+ if (out == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+
+ if (out_len) {
+ strlcat(out, ",", out_len + word_len + 6);
+ out_len++;
+ }
+ snprintf(out + out_len, word_len + 5, "uid=%s", user);
+ out_len = strlen(out);
+ }
+ if (got_gid) {
+ word_len = strlen(group);
+
+ out = (char *)realloc(out, out_len + 1 + word_len + 6);
+ if (out == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+
+ if (out_len) {
+ strlcat(out, ",", out_len + word_len + 6);
+ out_len++;
+ }
+ snprintf(out + out_len, word_len + 5, "gid=%s", group);
+ out_len = strlen(out);
+ }
+
free(*optionsp);
*optionsp = out;
return 0;
diff --git a/source3/configure.in b/source3/configure.in
index 84ae6f7e50..7272ae4d9a 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -65,10 +65,10 @@ AC_ARG_WITH(fhs,
mandir="\${prefix}/share/man"
logfilebase="\${VARDIR}/log/samba"
privatedir="\${CONFIGDIR}/private"
- libdir="\${prefix}/lib/samba"
+ test "${libdir}" || libdir="\${prefix}/lib/samba"
configdir="\${sysconfdir}/samba"
swatdir="\${DATADIR}/samba/swat"
- codepagedir="\${prefix}/lib/samba"
+ codepagedir="\${LIBDIR}"
statedir="\${VARDIR}/lib/samba"
cachedir="\${VARDIR}/lib/samba"
AC_DEFINE(FHS_COMPATIBLE, 1, [Whether to use fully FHS-compatible paths])
diff --git a/source3/include/smb.h b/source3/include/smb.h
index d58c124e6d..a725ae1392 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -242,6 +242,7 @@ typedef uint64_t NTTIME;
#define SID_MAX_SIZE ((size_t)(8+(MAXSUBAUTHS*4)))
+#define LOOKUP_NAME_NONE 0x00000000
#define LOOKUP_NAME_ISOLATED 0x00000001 /* Look up unqualified names */
#define LOOKUP_NAME_REMOTE 0x00000002 /* Ask others */
#define LOOKUP_NAME_GROUP 0x00000004 /* (unused) This is a NASTY hack for
@@ -250,7 +251,14 @@ typedef uint64_t NTTIME;
#define LOOKUP_NAME_EXPLICIT 0x00000008 /* Only include
explicitly mapped names and not
the Unix {User,Group} domain */
-#define LOOKUP_NAME_ALL (LOOKUP_NAME_ISOLATED|LOOKUP_NAME_REMOTE)
+#define LOOKUP_NAME_BUILTIN 0x00000010 /* builtin names */
+#define LOOKUP_NAME_WKN 0x00000020 /* well known names */
+#define LOOKUP_NAME_DOMAIN 0x00000040 /* only lookup own domain */
+#define LOOKUP_NAME_ALL (LOOKUP_NAME_ISOLATED\
+ |LOOKUP_NAME_REMOTE\
+ |LOOKUP_NAME_BUILTIN\
+ |LOOKUP_NAME_WKN\
+ |LOOKUP_NAME_DOMAIN)
/**
* @brief Security Identifier
diff --git a/source3/libsmb/clidgram.c b/source3/libsmb/clidgram.c
index 82f874f383..76630bd504 100644
--- a/source3/libsmb/clidgram.c
+++ b/source3/libsmb/clidgram.c
@@ -75,6 +75,12 @@ bool cli_send_mailslot(struct messaging_context *msg_ctx,
/* Setup the smb part. */
ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
memcpy(tmp,ptr,4);
+
+ if (smb_size + 17*2 + strlen(mailslot) + 1 + len > MAX_DGRAM_SIZE) {
+ DEBUG(0, ("cli_send_mailslot: Cannot write beyond end of packet\n"));
+ return False;
+ }
+
set_message(ptr,17,strlen(mailslot) + 1 + len,True);
memcpy(ptr,tmp,4);
diff --git a/source3/nmbd/nmbd_packets.c b/source3/nmbd/nmbd_packets.c
index b78ab5ba7e..349d36ce70 100644
--- a/source3/nmbd/nmbd_packets.c
+++ b/source3/nmbd/nmbd_packets.c
@@ -1918,6 +1918,12 @@ bool send_mailslot(bool unique, const char *mailslot,char *buf, size_t len,
/* Setup the smb part. */
ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
memcpy(tmp,ptr,4);
+
+ if (smb_size + 17*2 + strlen(mailslot) + 1 + len > MAX_DGRAM_SIZE) {
+ DEBUG(0, ("send_mailslot: Cannot write beyond end of packet\n"));
+ return false;
+ }
+
set_message(ptr,17,strlen(mailslot) + 1 + len,True);
memcpy(ptr,tmp,4);
diff --git a/source3/pam_smbpass/support.c b/source3/pam_smbpass/support.c
index 9d56bd4950..bc9481d9e9 100644
--- a/source3/pam_smbpass/support.c
+++ b/source3/pam_smbpass/support.c
@@ -61,10 +61,6 @@
void _cleanup(pam_handle_t *, void *, int);
char *_pam_delete(register char *);
- /* default configuration file location */
-
- const char *servicesf = get_dyn_CONFIGFILE();
-
/* syslogging function for errors and other information */
void _log_err( int err, const char *format, ... )
@@ -128,7 +124,7 @@
int set_ctrl( int flags, int argc, const char **argv )
{
int i = 0;
- const char *service_file = get_dyn_CONFIGFILE();
+ const char *service_file = NULL;
unsigned int ctrl;
ctrl = SMB_DEFAULTS; /* the default selection of options */
@@ -139,7 +135,7 @@ int set_ctrl( int flags, int argc, const char **argv )
set( SMB__NONULL, ctrl );
/* initialize service file location */
- service_file=servicesf;
+ service_file=get_dyn_CONFIGFILE();
if (flags & PAM_SILENT) {
set( SMB__QUIET, ctrl );
diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c
index bb54959e96..54db14fbfe 100644
--- a/source3/passdb/lookup_sid.c
+++ b/source3/passdb/lookup_sid.c
@@ -59,16 +59,19 @@ bool lookup_name(TALLOC_CTX *mem_ctx,
name = talloc_strdup(tmp_ctx, full_name);
}
- DEBUG(10,("lookup_name: %s => %s (domain), %s (name)\n",
- full_name, domain, name));
-
if ((domain == NULL) || (name == NULL)) {
DEBUG(0, ("talloc failed\n"));
TALLOC_FREE(tmp_ctx);
return false;
}
- if (strequal(domain, get_global_sam_name())) {
+ DEBUG(10,("lookup_name: %s => %s (domain), %s (name)\n",
+ full_name, domain, name));
+ DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags));
+
+ if ((flags & LOOKUP_NAME_DOMAIN) &&
+ strequal(domain, get_global_sam_name()))
+ {
/* It's our own domain, lookup the name in passdb */
if (lookup_global_sam_name(name, flags, &rid, &type)) {
@@ -80,8 +83,9 @@ bool lookup_name(TALLOC_CTX *mem_ctx,
return false;
}
- if (strequal(domain, builtin_domain_name())) {
-
+ if ((flags & LOOKUP_NAME_BUILTIN) &&
+ strequal(domain, builtin_domain_name()))
+ {
/* Explicit request for a name in BUILTIN */
if (lookup_builtin_name(name, &rid)) {
sid_copy(&sid, &global_sid_Builtin);
@@ -97,6 +101,7 @@ bool lookup_name(TALLOC_CTX *mem_ctx,
* domain yet at this point yet. This comes later. */
if ((domain[0] != '\0') &&
+ (flags & ~(LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED)) &&
(winbind_lookup_name(domain, name, &sid, &type))) {
goto ok;
}
@@ -131,14 +136,18 @@ bool lookup_name(TALLOC_CTX *mem_ctx,
/* 1. well-known names */
- if (lookup_wellknown_name(tmp_ctx, name, &sid, &domain)) {
+ if ((flags & LOOKUP_NAME_WKN) &&
+ lookup_wellknown_name(tmp_ctx, name, &sid, &domain))
+ {
type = SID_NAME_WKN_GRP;
goto ok;
}
/* 2. Builtin domain as such */
- if (strequal(name, builtin_domain_name())) {
+ if ((flags & (LOOKUP_NAME_BUILTIN|LOOKUP_NAME_REMOTE)) &&
+ strequal(name, builtin_domain_name()))
+ {
/* Swap domain and name */
tmp = name; name = domain; domain = tmp;
sid_copy(&sid, &global_sid_Builtin);
@@ -148,7 +157,9 @@ bool lookup_name(TALLOC_CTX *mem_ctx,
/* 3. Account domain */
- if (strequal(name, get_global_sam_name())) {
+ if ((flags & LOOKUP_NAME_DOMAIN) &&
+ strequal(name, get_global_sam_name()))
+ {
if (!secrets_fetch_domain_sid(name, &sid)) {
DEBUG(3, ("Could not fetch my SID\n"));
TALLOC_FREE(tmp_ctx);
@@ -162,7 +173,9 @@ bool lookup_name(TALLOC_CTX *mem_ctx,
/* 4. Primary domain */
- if (!IS_DC && strequal(name, lp_workgroup())) {
+ if ((flags & LOOKUP_NAME_DOMAIN) && !IS_DC &&
+ strequal(name, lp_workgroup()))
+ {
if (!secrets_fetch_domain_sid(name, &sid)) {
DEBUG(3, ("Could not fetch the domain SID\n"));
TALLOC_FREE(tmp_ctx);
@@ -177,7 +190,9 @@ bool lookup_name(TALLOC_CTX *mem_ctx,
/* 5. Trusted domains as such, to me it looks as if members don't do
this, tested an XP workstation in a NT domain -- vl */
- if (IS_DC && (pdb_get_trusteddom_pw(name, NULL, &sid, NULL))) {
+ if ((flags & LOOKUP_NAME_REMOTE) && IS_DC &&
+ (secrets_fetch_trusted_domain_password(name, NULL, &sid, NULL)))
+ {
/* Swap domain and name */
tmp = name; name = domain; domain = tmp;
type = SID_NAME_DOMAIN;
@@ -186,7 +201,9 @@ bool lookup_name(TALLOC_CTX *mem_ctx,
/* 6. Builtin aliases */
- if (lookup_builtin_name(name, &rid)) {
+ if ((flags & LOOKUP_NAME_BUILTIN) &&
+ lookup_builtin_name(name, &rid))
+ {
domain = talloc_strdup(tmp_ctx, builtin_domain_name());
sid_copy(&sid, &global_sid_Builtin);
sid_append_rid(&sid, rid);
@@ -199,7 +216,9 @@ bool lookup_name(TALLOC_CTX *mem_ctx,
/* Both cases are done by looking at our passdb */
- if (lookup_global_sam_name(name, flags, &rid, &type)) {
+ if ((flags & LOOKUP_NAME_DOMAIN) &&
+ lookup_global_sam_name(name, flags, &rid, &type))
+ {
domain = talloc_strdup(tmp_ctx, get_global_sam_name());
sid_copy(&sid, get_global_sam_sid());
sid_append_rid(&sid, rid);
diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c
index 2a4d4c4a0a..c4248bb48e 100644
--- a/source3/passdb/passdb.c
+++ b/source3/passdb/passdb.c
@@ -1521,46 +1521,99 @@ bool pdb_increment_bad_password_count(struct samu *sampass)
return True;
}
+bool is_trusted_domain_situation(const char *domain_name)
+{
+ return IS_DC &&
+ lp_allow_trusted_domains() &&
+ !strequal(domain_name, lp_workgroup());
+}
/*******************************************************************
- Wrapper around retrieving the trust account password
+ Wrapper around retrieving the clear text trust account password.
+ appropriate account name is stored in account_name.
+ Caller must free password, but not account_name.
*******************************************************************/
-bool get_trust_pw(const char *domain, uint8 ret_pwd[16], uint32 *channel)
+bool get_trust_pw_clear(const char *domain, char **ret_pwd,
+ const char **account_name, uint32 *channel)
{
- DOM_SID sid;
char *pwd;
time_t last_set_time;
/* if we are a DC and this is not our domain, then lookup an account
- for the domain trust */
+ * for the domain trust */
- if (IS_DC && !strequal(domain, lp_workgroup()) &&
- lp_allow_trusted_domains())
- {
- if (!pdb_get_trusteddom_pw(domain, &pwd, &sid, &last_set_time))
+ if (is_trusted_domain_situation(domain)) {
+ if (!pdb_get_trusteddom_pw(domain, ret_pwd, NULL,
+ &last_set_time))
{
DEBUG(0, ("get_trust_pw: could not fetch trust "
"account password for trusted domain %s\n",
domain));
- return False;
+ return false;
}
*channel = SEC_CHAN_DOMAIN;
- E_md4hash(pwd, ret_pwd);
- SAFE_FREE(pwd);
- return True;
+ if (account_name != NULL) {
+ *account_name = lp_workgroup();
+ }
+
+ return true;
}
/* Just get the account for the requested domain. In the future this
* might also cover to be member of more than one domain. */
- if (secrets_fetch_trust_account_password(domain, ret_pwd,
- &last_set_time, channel))
- return True;
+ pwd = secrets_fetch_machine_password(domain, &last_set_time, channel);
+
+ if (pwd != NULL) {
+ *ret_pwd = pwd;
+ if (account_name != NULL) {
+ *account_name = global_myname();
+ }
+
+ return true;
+ }
+
+ DEBUG(5, ("get_trust_pw_clear: could not fetch clear text trust "
+ "account password for domain %s\n", domain));
+ return false;
+}
+
+/*******************************************************************
+ Wrapper around retrieving the trust account password.
+ appropriate account name is stored in account_name.
+*******************************************************************/
+
+bool get_trust_pw_hash(const char *domain, uint8 ret_pwd[16],
+ const char **account_name, uint32 *channel)
+{
+ char *pwd = NULL;
+ time_t last_set_time;
+
+ if (get_trust_pw_clear(domain, &pwd, account_name, channel)) {
+ E_md4hash(pwd, ret_pwd);
+ SAFE_FREE(pwd);
+ return true;
+ } else if (is_trusted_domain_situation(domain)) {
+ return false;
+ }
+
+ /* as a fallback, try to get the hashed pwd directly from the tdb... */
+
+ if (secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
+ &last_set_time,
+ channel))
+ {
+ if (account_name != NULL) {
+ *account_name = global_myname();
+ }
+
+ return true;
+ }
- DEBUG(5, ("get_trust_pw: could not fetch trust account "
+ DEBUG(5, ("get_trust_pw_hash: could not fetch trust account "
"password for domain %s\n", domain));
return False;
}
diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c
index a4cb76602a..fde7fc0968 100644
--- a/source3/passdb/secrets.c
+++ b/source3/passdb/secrets.c
@@ -284,27 +284,19 @@ uint32 get_default_sec_channel(void)
/************************************************************************
Routine to get the trust account password for a domain.
+ This only tries to get the legacy hashed version of the password.
The user of this function must have locked the trust password file using
the above secrets_lock_trust_account_password().
************************************************************************/
-bool secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
- time_t *pass_last_set_time,
- uint32 *channel)
+bool secrets_fetch_trust_account_password_legacy(const char *domain,
+ uint8 ret_pwd[16],
+ time_t *pass_last_set_time,
+ uint32 *channel)
{
struct machine_acct_pass *pass;
- char *plaintext;
size_t size = 0;
- plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
- channel);
- if (plaintext) {
- DEBUG(4,("Using cleartext machine password\n"));
- E_md4hash(plaintext, ret_pwd);
- SAFE_FREE(plaintext);
- return True;
- }
-
if (!(pass = (struct machine_acct_pass *)secrets_fetch(
trust_keystr(domain), &size))) {
DEBUG(5, ("secrets_fetch failed!\n"));
@@ -337,6 +329,32 @@ bool secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
return True;
}
+/************************************************************************
+ Routine to get the trust account password for a domain.
+ The user of this function must have locked the trust password file using
+ the above secrets_lock_trust_account_password().
+************************************************************************/
+
+bool secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
+ time_t *pass_last_set_time,
+ uint32 *channel)
+{
+ char *plaintext;
+
+ plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
+ channel);
+ if (plaintext) {
+ DEBUG(4,("Using cleartext machine password\n"));
+ E_md4hash(plaintext, ret_pwd);
+ SAFE_FREE(plaintext);
+ return True;
+ }
+
+ return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
+ pass_last_set_time,
+ channel);
+}
+
/**
* Pack SID passed by pointer
*
@@ -558,20 +576,6 @@ bool secrets_fetch_trusted_domain_password(const char *domain, char** pwd,
return True;
}
-/************************************************************************
- Routine to set the trust account password for a domain.
-************************************************************************/
-
-bool secrets_store_trust_account_password(const char *domain, uint8 new_pwd[16])
-{
- struct machine_acct_pass pass;
-
- pass.mod_time = time(NULL);
- memcpy(pass.hash, new_pwd, 16);
-
- return secrets_store(trust_keystr(domain), (void *)&pass, sizeof(pass));
-}
-
/**
* Routine to store the password for trusted domain
*
@@ -722,15 +726,6 @@ char *secrets_fetch_machine_password(const char *domain,
}
/************************************************************************
- Routine to delete the machine trust account password file for a domain.
-************************************************************************/
-
-bool trust_password_delete(const char *domain)
-{
- return secrets_delete(trust_keystr(domain));
-}
-
-/************************************************************************
Routine to delete the password for trusted domain
************************************************************************/
diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c
index 37558a7ff0..f61ea95d04 100644
--- a/source3/rpc_client/cli_pipe.c
+++ b/source3/rpc_client/cli_pipe.c
@@ -2424,49 +2424,29 @@ struct rpc_pipe_client *cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
}
/****************************************************************************
- Open a netlogon pipe and get the schannel session key.
- Now exposed to external callers.
+ Get a the schannel session key out of an already opened netlogon pipe.
****************************************************************************/
-
-struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli,
- const char *domain,
- uint32 *pneg_flags,
- NTSTATUS *perr)
+static bool get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
+ struct cli_state *cli,
+ const char *domain,
+ uint32 *pneg_flags,
+ NTSTATUS *perr)
{
- struct rpc_pipe_client *netlogon_pipe = NULL;
uint32 sec_chan_type = 0;
unsigned char machine_pwd[16];
- fstring machine_account;
-
- netlogon_pipe = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, perr);
- if (!netlogon_pipe) {
- return NULL;
- }
+ const char *machine_account;
/* Get the machine account credentials from secrets.tdb. */
- if (!get_trust_pw(domain, machine_pwd, &sec_chan_type)) {
+ if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
+ &sec_chan_type))
+ {
DEBUG(0, ("get_schannel_session_key: could not fetch "
"trust account password for domain '%s'\n",
domain));
- cli_rpc_pipe_close(netlogon_pipe);
*perr = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
- return NULL;
+ return false;
}
- /* A DC should use DOMAIN$ as its account name.
- A member server can only use it's machine name since it
- does not have an account in a trusted domain.
-
- We don't check the domain against lp_workgroup() here since
- 'net ads join' has to continue to work with only the realm
- specified in smb.conf. -- jerry */
-
- if ( IS_DC && !strequal(domain, lp_workgroup()) && lp_allow_trusted_domains()) {
- fstrcpy( machine_account, lp_workgroup() );
- } else {
- fstrcpy(machine_account, global_myname());
- }
-
*perr = rpccli_netlogon_setup_creds(netlogon_pipe,
cli->desthost, /* server name */
domain, /* domain */
@@ -2477,11 +2457,10 @@ struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli,
pneg_flags);
if (!NT_STATUS_IS_OK(*perr)) {
- DEBUG(3,("get_schannel_session_key: rpccli_netlogon_setup_creds "
+ DEBUG(3,("get_schannel_session_key_common: rpccli_netlogon_setup_creds "
"failed with result %s to server %s, domain %s, machine account %s.\n",
nt_errstr(*perr), cli->desthost, domain, machine_account ));
- cli_rpc_pipe_close(netlogon_pipe);
- return NULL;
+ return false;
}
if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
@@ -2489,6 +2468,34 @@ struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli,
cli->desthost));
cli_rpc_pipe_close(netlogon_pipe);
*perr = NT_STATUS_INVALID_NETWORK_RESPONSE;
+ return false;
+ }
+
+ return true;
+}
+
+/****************************************************************************
+ Open a netlogon pipe and get the schannel session key.
+ Now exposed to external callers.
+ ****************************************************************************/
+
+
+struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli,
+ const char *domain,
+ uint32 *pneg_flags,
+ NTSTATUS *perr)
+{
+ struct rpc_pipe_client *netlogon_pipe = NULL;
+
+ netlogon_pipe = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, perr);
+ if (!netlogon_pipe) {
+ return NULL;
+ }
+
+ if (!get_schannel_session_key_common(netlogon_pipe, cli, domain,
+ pneg_flags, perr))
+ {
+ cli_rpc_pipe_close(netlogon_pipe);
return NULL;
}
@@ -2560,61 +2567,16 @@ static struct rpc_pipe_client *get_schannel_session_key_auth_ntlmssp(struct cli_
NTSTATUS *perr)
{
struct rpc_pipe_client *netlogon_pipe = NULL;
- uint32 sec_chan_type = 0;
- unsigned char machine_pwd[16];
- fstring machine_account;
netlogon_pipe = cli_rpc_pipe_open_spnego_ntlmssp(cli, PI_NETLOGON, PIPE_AUTH_LEVEL_PRIVACY, domain, username, password, perr);
if (!netlogon_pipe) {
return NULL;
}
- /* Get the machine account credentials from secrets.tdb. */
- if (!get_trust_pw(domain, machine_pwd, &sec_chan_type)) {
- DEBUG(0, ("get_schannel_session_key_auth_ntlmssp: could not fetch "
- "trust account password for domain '%s'\n",
- domain));
- cli_rpc_pipe_close(netlogon_pipe);
- *perr = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
- return NULL;
- }
-
- /* if we are a DC and this is a trusted domain, then we need to use our
- domain name in the net_req_auth2() request */
-
- if ( IS_DC && !strequal(domain, lp_workgroup()) && lp_allow_trusted_domains()) {
- fstrcpy( machine_account, lp_workgroup() );
- } else {
- /* Hmmm. Is this correct for trusted domains when we're a member server ? JRA. */
- if (strequal(domain, lp_workgroup())) {
- fstrcpy(machine_account, global_myname());
- } else {
- fstrcpy(machine_account, domain);
- }
- }
-
- *perr = rpccli_netlogon_setup_creds(netlogon_pipe,
- cli->desthost, /* server name */
- domain, /* domain */
- global_myname(), /* client name */
- machine_account, /* machine account name */
- machine_pwd,
- sec_chan_type,
- pneg_flags);
-
- if (!NT_STATUS_IS_OK(*perr)) {
- DEBUG(3,("get_schannel_session_key_auth_ntlmssp: rpccli_netlogon_setup_creds "
- "failed with result %s\n",
- nt_errstr(*perr) ));
- cli_rpc_pipe_close(netlogon_pipe);
- return NULL;
- }
-
- if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
- DEBUG(3, ("get_schannel_session_key_auth_ntlmssp: Server %s did not offer schannel\n",
- cli->desthost));
+ if (!get_schannel_session_key_common(netlogon_pipe, cli, domain,
+ pneg_flags, perr))
+ {
cli_rpc_pipe_close(netlogon_pipe);
- *perr = NT_STATUS_INVALID_NETWORK_RESPONSE;
return NULL;
}
diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c
index 20655082a5..c5f0c7b6ab 100644
--- a/source3/rpc_server/srv_lsa_nt.c
+++ b/source3/rpc_server/srv_lsa_nt.c
@@ -1035,6 +1035,31 @@ NTSTATUS _lsa_lookup_sids3(pipes_struct *p,
return r_u->status;
}
+static int lsa_lookup_level_to_flags(uint16 level)
+{
+ int flags;
+
+ switch (level) {
+ case 1:
+ flags = LOOKUP_NAME_ALL;
+ break;
+ case 2:
+ flags = LOOKUP_NAME_DOMAIN|LOOKUP_NAME_REMOTE|LOOKUP_NAME_ISOLATED;
+ break;
+ case 3:
+ flags = LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED;
+ break;
+ case 4:
+ case 5:
+ case 6:
+ default:
+ flags = LOOKUP_NAME_NONE;
+ break;
+ }
+
+ return flags;
+}
+
/***************************************************************************
lsa_reply_lookup_names
***************************************************************************/
@@ -1054,10 +1079,7 @@ NTSTATUS _lsa_lookup_names(pipes_struct *p,LSA_Q_LOOKUP_NAMES *q_u, LSA_R_LOOKUP
DEBUG(5,("_lsa_lookup_names: truncating name lookup list to %d\n", num_entries));
}
- /* Probably the lookup_level is some sort of bitmask. */
- if (q_u->lookup_level == 1) {
- flags = LOOKUP_NAME_ALL;
- }
+ flags = lsa_lookup_level_to_flags(q_u->lookup_level);
ref = TALLOC_ZERO_P(p->mem_ctx, DOM_R_REF);
if (!ref) {
@@ -1123,11 +1145,8 @@ NTSTATUS _lsa_lookup_names2(pipes_struct *p, LSA_Q_LOOKUP_NAMES2 *q_u, LSA_R_LOO
num_entries = MAX_LOOKUP_SIDS;
DEBUG(5,("_lsa_lookup_names2: truncating name lookup list to %d\n", num_entries));
}
-
- /* Probably the lookup_level is some sort of bitmask. */
- if (q_u->lookup_level == 1) {
- flags = LOOKUP_NAME_ALL;
- }
+
+ flags = lsa_lookup_level_to_flags(q_u->lookup_level);
ref = TALLOC_ZERO_P(p->mem_ctx, DOM_R_REF);
if (ref == NULL) {
diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c
index 3f6544965d..cb366a293c 100644
--- a/source3/winbindd/winbindd_cm.c
+++ b/source3/winbindd/winbindd_cm.c
@@ -635,6 +635,40 @@ static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain,
return True;
}
+/**
+ * Helper function to assemble trust password and account name
+ */
+static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
+ char **machine_password,
+ char **machine_account,
+ char **machine_krb5_principal)
+{
+ const char *account_name;
+
+ if (!get_trust_pw_clear(domain->name, machine_password,
+ &account_name, NULL))
+ {
+ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+ }
+
+ if ((machine_account != NULL) &&
+ (asprintf(machine_account, "%s$", account_name) == -1))
+ {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* this is at least correct when domain is our domain,
+ * which is the only case, when this is currently used: */
+ if ((machine_krb5_principal != NULL) &&
+ (asprintf(machine_krb5_principal, "%s$@%s", account_name,
+ domain->alt_name) == -1))
+ {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ return NT_STATUS_OK;
+}
+
/************************************************************************
Given a fd with a just-connected TCP connection to a DC, open a connection
to the pipe.
@@ -646,8 +680,12 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
struct cli_state **cli,
bool *retry)
{
- char *machine_password, *machine_krb5_principal, *machine_account;
- char *ipc_username, *ipc_domain, *ipc_password;
+ char *machine_password = NULL;
+ char *machine_krb5_principal = NULL;
+ char *machine_account = NULL;
+ char *ipc_username = NULL;
+ char *ipc_domain = NULL;
+ char *ipc_password = NULL;
bool got_mutex;
@@ -661,23 +699,6 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n",
controller, domain->name ));
- machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
- NULL);
-
- if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
- SAFE_FREE(machine_password);
- return NT_STATUS_NO_MEMORY;
- }
-
- if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
- lp_realm()) == -1) {
- SAFE_FREE(machine_account);
- SAFE_FREE(machine_password);
- return NT_STATUS_NO_MEMORY;
- }
-
- cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
-
*retry = True;
got_mutex = secrets_named_mutex(controller,
@@ -734,10 +755,20 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
result = NT_STATUS_UNSUCCESSFUL;
goto done;
}
-
- if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
+
+ if (!is_trusted_domain_situation(domain->name) &&
+ (*cli)->protocol >= PROTOCOL_NT1 &&
+ (*cli)->capabilities & CAP_EXTENDED_SECURITY)
+ {
ADS_STATUS ads_status;
+ result = get_trust_creds(domain, &machine_password,
+ &machine_account,
+ &machine_krb5_principal);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
if (lp_security() == SEC_ADS) {
/* Try a krb5 session */
@@ -752,7 +783,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
ads_status = cli_session_setup_spnego(*cli,
machine_krb5_principal,
machine_password,
- lp_workgroup());
+ domain->name);
if (!ADS_ERR_OK(ads_status)) {
DEBUG(4,("failed kerberos session setup with %s\n",
@@ -762,7 +793,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
result = ads_ntstatus(ads_status);
if (NT_STATUS_IS_OK(result)) {
/* Ensure creds are stored for NTLMSSP authenticated pipe access. */
- cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
+ cli_init_creds(*cli, machine_account, domain->name, machine_password);
goto session_setup_done;
}
}
@@ -772,12 +803,12 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
DEBUG(5, ("connecting to %s from %s with username "
"[%s]\\[%s]\n", controller, global_myname(),
- lp_workgroup(), machine_account));
+ domain->name, machine_account));
ads_status = cli_session_setup_spnego(*cli,
machine_account,
machine_password,
- lp_workgroup());
+ domain->name);
if (!ADS_ERR_OK(ads_status)) {
DEBUG(4, ("authenticated session setup failed with %s\n",
ads_errstr(ads_status)));
@@ -786,15 +817,17 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
result = ads_ntstatus(ads_status);
if (NT_STATUS_IS_OK(result)) {
/* Ensure creds are stored for NTLMSSP authenticated pipe access. */
- cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
+ cli_init_creds(*cli, machine_account, domain->name, machine_password);
goto session_setup_done;
}
}
- /* Fall back to non-kerberos session setup */
+ /* Fall back to non-kerberos session setup with auth_user */
(*cli)->use_kerberos = False;
+ cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
+
if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
(strlen(ipc_username) > 0)) {
@@ -1935,6 +1968,9 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
fstring conn_pwd;
struct dcinfo *p_dcinfo;
+ char *machine_password = NULL;
+ char *machine_account = NULL;
+ char *domain_name = NULL;
result = init_dc_connection(domain);
if (!NT_STATUS_IS_OK(result)) {
@@ -1957,34 +1993,46 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
if ((conn->cli->user_name[0] == '\0') ||
(conn->cli->domain[0] == '\0') ||
- (conn_pwd[0] == '\0')) {
- DEBUG(10, ("cm_connect_sam: No no user available for "
- "domain %s, trying schannel\n", conn->cli->domain));
+ (conn_pwd[0] == '\0'))
+ {
+ result = get_trust_creds(domain, &machine_password,
+ &machine_account, NULL);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10, ("cm_connect_sam: No no user available for "
+ "domain %s, trying schannel\n", conn->cli->domain));
+ goto schannel;
+ }
+ domain_name = domain->name;
goto schannel;
+ } else {
+ machine_password = conn_pwd;
+ machine_account = conn->cli->user_name;
+ domain_name = conn->cli->domain;
}
+
/* We have an authenticated connection. Use a NTLMSSP SPNEGO
authenticated SAMR pipe with sign & seal. */
conn->samr_pipe =
cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR,
PIPE_AUTH_LEVEL_PRIVACY,
- conn->cli->domain,
- conn->cli->user_name,
- conn_pwd, &result);
+ domain_name,
+ machine_account,
+ machine_password, &result);
if (conn->samr_pipe == NULL) {
DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
"pipe for domain %s using NTLMSSP "
"authenticated pipe: user %s\\%s. Error was "
- "%s\n", domain->name, conn->cli->domain,
- conn->cli->user_name, nt_errstr(result)));
+ "%s\n", domain->name, domain_name,
+ machine_account, nt_errstr(result)));
goto schannel;
}
DEBUG(10,("cm_connect_sam: connected to SAMR pipe for "
"domain %s using NTLMSSP authenticated "
"pipe: user %s\\%s\n", domain->name,
- conn->cli->domain, conn->cli->user_name ));
+ domain_name, machine_account));
result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
SEC_RIGHTS_MAXIMUM_ALLOWED,
@@ -2069,6 +2117,8 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
*cli = conn->samr_pipe;
*sam_handle = conn->sam_domain_handle;
+ SAFE_FREE(machine_password);
+ SAFE_FREE(machine_account);
return result;
}
@@ -2219,10 +2269,6 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
return NT_STATUS_OK;
}
- if ((IS_DC || domain->primary) && !get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
- return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
- }
-
netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON,
&result);
if (netlogon_pipe == NULL) {
@@ -2234,27 +2280,16 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
neg_flags &= ~NETLOGON_NEG_SCHANNEL;
goto no_schannel;
}
-
+
if (lp_client_schannel() != False) {
neg_flags |= NETLOGON_NEG_SCHANNEL;
}
- /* if we are a DC and this is a trusted domain, then we need to use our
- domain name in the net_req_auth2() request */
-
- if ( IS_DC
- && !strequal(domain->name, lp_workgroup())
- && lp_allow_trusted_domains() )
+ if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name,
+ &sec_chan_type))
{
- account_name = lp_workgroup();
- } else {
- account_name = domain->primary ?
- global_myname() : domain->name;
- }
-
- if (account_name == NULL) {
cli_rpc_pipe_close(netlogon_pipe);
- return NT_STATUS_NO_MEMORY;
+ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
}
result = rpccli_netlogon_setup_creds(