summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2006-07-20 19:44:11 +0000
committerGerald Carter <jerry@samba.org>2006-07-20 19:44:11 +0000
commit64355e40a8b3545f28da465241b772fbd80d48ce (patch)
tree426226d4533390df3a789c7c6fa86f28b3d61662
parent57c21f4a80371d09288266cf797773a3f0fbd0b9 (diff)
downloadsamba-64355e40a8b3545f28da465241b772fbd80d48ce.tar.gz
samba-64355e40a8b3545f28da465241b772fbd80d48ce.tar.xz
samba-64355e40a8b3545f28da465241b772fbd80d48ce.zip
r17161: sync files from SAMBA_3_0_23 branch
-rw-r--r--source/auth/auth_util.c3
-rw-r--r--source/nsswitch/winbindd_group.c8
-rw-r--r--source/nsswitch/winbindd_util.c28
-rw-r--r--source/passdb/pdb_interface.c29
-rw-r--r--source/passdb/pdb_ldap.c14
-rw-r--r--source/passdb/pdb_tdb.c20
-rw-r--r--source/rpc_server/srv_samr_nt.c32
-rw-r--r--source/smbd/open.c160
-rw-r--r--source/utils/net_ads.c168
9 files changed, 306 insertions, 156 deletions
diff --git a/source/auth/auth_util.c b/source/auth/auth_util.c
index 493d7393d07..5298560ba43 100644
--- a/source/auth/auth_util.c
+++ b/source/auth/auth_util.c
@@ -955,7 +955,8 @@ NTSTATUS create_local_token(auth_serversupplied_info *server_info)
return NT_STATUS_NO_MEMORY;
}
- if (server_info->was_mapped) {
+ if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
+ server_info->was_mapped) {
status = create_token_from_username(server_info,
server_info->unix_name,
server_info->guest,
diff --git a/source/nsswitch/winbindd_group.c b/source/nsswitch/winbindd_group.c
index c0da45d8d03..5528b6c78e4 100644
--- a/source/nsswitch/winbindd_group.c
+++ b/source/nsswitch/winbindd_group.c
@@ -42,7 +42,7 @@ static BOOL fill_grent(struct winbindd_gr *gr, const char *dom_name,
{
fstring full_group_name;
- fill_domain_username( full_group_name, dom_name, gr_name, False);
+ fill_domain_username( full_group_name, dom_name, gr_name, True );
gr->gr_gid = unix_gid;
@@ -146,7 +146,7 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
/* Append domain name */
- fill_domain_username(name, domain->name, the_name, False);
+ fill_domain_username(name, domain->name, the_name, True);
len = strlen(name);
@@ -752,7 +752,7 @@ void winbindd_getgrent(struct winbindd_cli_state *state)
/* Fill in group entry */
fill_domain_username(domain_group_name, ent->domain_name,
- name_list[ent->sam_entry_index].acct_name, False);
+ name_list[ent->sam_entry_index].acct_name, True);
result = fill_grent(&group_list[group_list_ndx],
ent->domain_name,
@@ -929,7 +929,7 @@ void winbindd_list_groups(struct winbindd_cli_state *state)
groups.sam_entries)[i].acct_name;
fstring name;
- fill_domain_username(name, domain->name, group_name, False);
+ fill_domain_username(name, domain->name, group_name, True);
/* Append to extra data */
memcpy(&extra_data[extra_data_len], name,
strlen(name));
diff --git a/source/nsswitch/winbindd_util.c b/source/nsswitch/winbindd_util.c
index 67b94817adb..7e7ada52d73 100644
--- a/source/nsswitch/winbindd_util.c
+++ b/source/nsswitch/winbindd_util.c
@@ -812,14 +812,28 @@ BOOL is_in_gid_range(gid_t gid)
/* Is this a domain which we may assume no DOMAIN\ prefix? */
-static BOOL assume_domain(const char *domain) {
- if ((lp_winbind_use_default_domain()
- || lp_winbind_trusted_domains_only()) &&
- strequal(lp_workgroup(), domain))
- return True;
+static BOOL assume_domain(const char *domain)
+{
+ /* never assume the domain on a standalone server */
+
+ if ( lp_server_role() == ROLE_STANDALONE )
+ return False;
+
+ /* domain member servers may possibly assume for the domain name */
+
+ if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
+ if ( !strequal(lp_workgroup(), domain) )
+ return False;
+
+ if ( lp_winbind_use_default_domain() || lp_winbind_trusted_domains_only() )
+ return True;
+ }
+
+ /* only left with a domain controller */
- if (strequal(get_global_sam_name(), domain))
+ if ( strequal(get_global_sam_name(), domain) ) {
return True;
+ }
return False;
}
@@ -832,7 +846,7 @@ BOOL parse_domain_user(const char *domuser, fstring domain, fstring user)
if ( !p ) {
fstrcpy(user, domuser);
-
+
if ( assume_domain(lp_workgroup())) {
fstrcpy(domain, lp_workgroup());
} else {
diff --git a/source/passdb/pdb_interface.c b/source/passdb/pdb_interface.c
index 5d70c2c1227..3e47c97b04c 100644
--- a/source/passdb/pdb_interface.c
+++ b/source/passdb/pdb_interface.c
@@ -344,6 +344,7 @@ static NTSTATUS pdb_default_create_user(struct pdb_methods *methods,
if ( !(pwd = Get_Pwnam_alloc(tmp_ctx, name)) ) {
pstring add_script;
int add_ret;
+ fstring name2;
if ((acb_info & ACB_NORMAL) && name[strlen(name)-1] != '$') {
pstrcpy(add_script, lp_adduser_script());
@@ -357,7 +358,11 @@ static NTSTATUS pdb_default_create_user(struct pdb_methods *methods,
return NT_STATUS_NO_SUCH_USER;
}
- all_string_sub(add_script, "%u", name, sizeof(add_script));
+ /* lowercase the username before creating the Unix account for
+ compatibility with previous Samba releases */
+ fstrcpy( name2, name );
+ strlower_m( name2 );
+ all_string_sub(add_script, "%u", name2, sizeof(add_script));
add_ret = smbrun(add_script,NULL);
DEBUG(add_ret ? 0 : 3, ("_samr_create_user: Running the command `%s' gave %d\n",
add_script, add_ret));
@@ -383,6 +388,10 @@ static NTSTATUS pdb_default_create_user(struct pdb_methods *methods,
return NT_STATUS_INTERNAL_ERROR;
}
+ /* Use the username case specified in the original request */
+
+ pdb_set_username( sam_pass, name, PDB_SET );
+
/* Disable the account on creation, it does not have a reasonable password yet. */
acb_info |= ACB_DISABLED;
@@ -435,6 +444,7 @@ static NTSTATUS pdb_default_delete_user(struct pdb_methods *methods,
struct samu *sam_acct)
{
NTSTATUS status;
+ fstring username;
status = pdb_delete_sam_account(sam_acct);
if (!NT_STATUS_IS_OK(status)) {
@@ -447,7 +457,14 @@ static NTSTATUS pdb_default_delete_user(struct pdb_methods *methods,
* not necessary present and maybe the sysadmin doesn't want to delete
* the unix side
*/
- smb_delete_user( pdb_get_username(sam_acct) );
+
+ /* always lower case the username before handing it off to
+ external scripts */
+
+ fstrcpy( username, pdb_get_username(sam_acct) );
+ strlower_m( username );
+
+ smb_delete_user( username );
return status;
}
@@ -504,6 +521,7 @@ NTSTATUS pdb_rename_sam_account(struct samu *oldname, const char *newname)
{
struct pdb_methods *pdb = pdb_get_methods();
uid_t uid;
+ NTSTATUS status;
if (csamuser != NULL) {
TALLOC_FREE(csamuser);
@@ -520,7 +538,12 @@ NTSTATUS pdb_rename_sam_account(struct samu *oldname, const char *newname)
return NT_STATUS_ACCESS_DENIED;
}
- return pdb->rename_sam_account(pdb, oldname, newname);
+ status = pdb->rename_sam_account(pdb, oldname, newname);
+
+ /* always flush the cache here just to be safe */
+ flush_pwnam_cache();
+
+ return status;
}
NTSTATUS pdb_update_login_attempts(struct samu *sam_acct, BOOL success)
diff --git a/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c
index 4a9794e1861..e4486226264 100644
--- a/source/passdb/pdb_ldap.c
+++ b/source/passdb/pdb_ldap.c
@@ -1830,6 +1830,7 @@ static NTSTATUS ldapsam_rename_sam_account(struct pdb_methods *my_methods,
const char *oldname;
int rc;
pstring rename_script;
+ fstring oldname_lower, newname_lower;
if (!old_acct) {
DEBUG(0, ("ldapsam_rename_sam_account: old_acct was NULL!\n"));
@@ -1851,10 +1852,17 @@ static NTSTATUS ldapsam_rename_sam_account(struct pdb_methods *my_methods,
DEBUG (3, ("ldapsam_rename_sam_account: Renaming user %s to %s.\n",
oldname, newname));
- /* we have to allow the account name to end with a '$' */
- string_sub2(rename_script, "%unew", newname, sizeof(pstring),
+ /* We have to allow the account name to end with a '$'.
+ Also, follow the semantics in _samr_create_user() and lower case the
+ posix name but preserve the case in passdb */
+
+ fstrcpy( oldname_lower, oldname );
+ strlower_m( oldname_lower );
+ fstrcpy( newname_lower, newname );
+ strlower_m( newname_lower );
+ string_sub2(rename_script, "%unew", newname_lower, sizeof(pstring),
True, False, True);
- string_sub2(rename_script, "%uold", oldname, sizeof(pstring),
+ string_sub2(rename_script, "%uold", oldname_lower, sizeof(pstring),
True, False, True);
rc = smbrun(rename_script, NULL);
diff --git a/source/passdb/pdb_tdb.c b/source/passdb/pdb_tdb.c
index f3ae4b7b02e..45fdd12b273 100644
--- a/source/passdb/pdb_tdb.c
+++ b/source/passdb/pdb_tdb.c
@@ -1388,6 +1388,8 @@ static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
pstring rename_script;
BOOL interim_account = False;
int rename_ret;
+ fstring oldname_lower;
+ fstring newname_lower;
/* can't do anything without an external script */
@@ -1431,11 +1433,19 @@ static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
goto done;
}
- /* rename the posix user */
- string_sub2(rename_script, "%unew", newname, sizeof(pstring),
- True, False, True);
- string_sub2(rename_script, "%uold", pdb_get_username(old_acct),
- sizeof(pstring), True, False, True);
+ /* Rename the posix user. Follow the semantics of _samr_create_user()
+ so that we lower case the posix name but preserve the case in passdb */
+
+ fstrcpy( oldname_lower, pdb_get_username(old_acct) );
+ strlower_m( oldname_lower );
+
+ fstrcpy( newname_lower, newname );
+ strlower_m( newname_lower );
+
+ string_sub2(rename_script, "%unew", newname_lower, sizeof(pstring),
+ True, False, True);
+ string_sub2(rename_script, "%uold", oldname_lower, sizeof(pstring),
+ True, False, True);
rename_ret = smbrun(rename_script, NULL);
DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret));
diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c
index da2bb8c3b56..7422b18d46e 100644
--- a/source/rpc_server/srv_samr_nt.c
+++ b/source/rpc_server/srv_samr_nt.c
@@ -2463,8 +2463,6 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u,
return NT_STATUS_NO_MEMORY;
}
- strlower_m(account);
-
nt_status = can_create(p->mem_ctx, account);
if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
@@ -3203,7 +3201,7 @@ static NTSTATUS set_user_info_23(TALLOC_CTX *mem_ctx, SAM_USER_INFO_23 *id23,
if ( ( (acct_ctrl & ACB_DOMTRUST) == ACB_DOMTRUST ) ||
( (acct_ctrl & ACB_WSTRUST) == ACB_WSTRUST) ||
( (acct_ctrl & ACB_SVRTRUST) == ACB_SVRTRUST) ) {
- DEBUG(5, ("Changing trust account or non-unix-user password, not updating /etc/passwd\n"));
+ DEBUG(5, ("Changing trust account. Not updating /etc/passwd\n"));
} else {
/* update the UNIX password */
if (lp_unix_password_sync() ) {
@@ -3385,10 +3383,25 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
if (!get_lsa_policy_samr_sid(p, pol, &sid, &acc_granted, &disp_info))
return NT_STATUS_INVALID_HANDLE;
- /* observed when joining an XP client to a Samba domain */
+ /* This is tricky. A WinXP domain join sets
+ (SA_RIGHT_USER_SET_PASSWORD|SA_RIGHT_USER_SET_ATTRIBUTES|SA_RIGHT_USER_ACCT_FLAGS_EXPIRY)
+ The MMC lusrmgr plugin includes these perms and more in the SamrOpenUser(). But the
+ standard Win32 API calls just ask for SA_RIGHT_USER_SET_PASSWORD in the SamrOpenUser().
+ This should be enough for levels 18, 24, 25,& 26. Info level 23 can set more so
+ we'll use the set from the WinXP join as the basis. */
+
+ switch (switch_value) {
+ case 18:
+ case 24:
+ case 25:
+ case 26:
+ acc_required = SA_RIGHT_USER_SET_PASSWORD;
+ break;
+ default:
+ acc_required = SA_RIGHT_USER_SET_PASSWORD | SA_RIGHT_USER_SET_ATTRIBUTES | SA_RIGHT_USER_ACCT_FLAGS_EXPIRY;
+ break;
+ }
- acc_required = SA_RIGHT_USER_SET_PASSWORD | SA_RIGHT_USER_SET_ATTRIBUTES | SA_RIGHT_USER_ACCT_FLAGS_EXPIRY;
-
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, acc_required, "_samr_set_userinfo"))) {
return r_u->status;
}
@@ -4027,6 +4040,7 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM
BOOL can_add_accounts;
uint32 acb_info;
DISP_INFO *disp_info = NULL;
+ BOOL ret;
DEBUG(5, ("_samr_delete_dom_user: %d\n", __LINE__));
@@ -4046,7 +4060,11 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM
return NT_STATUS_NO_MEMORY;
}
- if(!pdb_getsampwsid(sam_pass, &user_sid)) {
+ become_root();
+ ret = pdb_getsampwsid(sam_pass, &user_sid);
+ unbecome_root();
+
+ if( !ret ) {
DEBUG(5,("_samr_delete_dom_user:User %s doesn't exist.\n",
sid_string_static(&user_sid)));
TALLOC_FREE(sam_pass);
diff --git a/source/smbd/open.c b/source/smbd/open.c
index 94441c5df9b..a3c3cc4fc95 100644
--- a/source/smbd/open.c
+++ b/source/smbd/open.c
@@ -185,7 +185,8 @@ static BOOL open_file(files_struct *fsp,
SMB_STRUCT_STAT *psbuf,
int flags,
mode_t unx_mode,
- uint32 access_mask)
+ uint32 access_mask, /* client requested access mask. */
+ uint32 open_access_mask) /* what we're actually using in the open. */
{
int accmode = (flags & O_ACCMODE);
int local_flags = flags;
@@ -239,7 +240,7 @@ static BOOL open_file(files_struct *fsp,
local_flags = (flags & ~O_ACCMODE)|O_RDWR;
}
- if ((access_mask & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ||
+ if ((open_access_mask & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ||
(!file_existed && (local_flags & O_CREAT)) ||
((local_flags & O_TRUNC) == O_TRUNC) ) {
@@ -1112,6 +1113,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
uint16 mid = get_current_mid();
struct timeval request_time = timeval_zero();
struct share_mode_lock *lck = NULL;
+ uint32 open_access_mask = access_mask;
NTSTATUS status;
if (conn->printer) {
@@ -1202,12 +1204,14 @@ files_struct *open_file_ntcreate(connection_struct *conn,
/* If file exists replace/overwrite. If file doesn't
* exist create. */
flags2 |= (O_CREAT | O_TRUNC);
+ open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */
break;
case FILE_OVERWRITE_IF:
/* If file exists replace/overwrite. If file doesn't
* exist create. */
flags2 |= (O_CREAT | O_TRUNC);
+ open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */
break;
case FILE_OPEN:
@@ -1234,6 +1238,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
return NULL;
}
flags2 |= O_TRUNC;
+ open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */
break;
case FILE_CREATE:
@@ -1286,7 +1291,10 @@ files_struct *open_file_ntcreate(connection_struct *conn,
/* This is a nasty hack - must fix... JRA. */
if (access_mask == MAXIMUM_ALLOWED_ACCESS) {
- access_mask = FILE_GENERIC_ALL;
+ open_access_mask = access_mask = FILE_GENERIC_ALL;
+ if (flags2 & O_TRUNC) {
+ open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */
+ }
}
/*
@@ -1351,7 +1359,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
fsp->inode = psbuf->st_ino;
fsp->share_access = share_access;
fsp->fh->private_options = create_options;
- fsp->access_mask = access_mask;
+ fsp->access_mask = open_access_mask; /* We change this to the requested access_mask after the open is done. */
/* Ensure no SAMBA_PRIVATE bits can be set. */
fsp->oplock_type = (oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK);
@@ -1382,6 +1390,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
return NULL;
}
+ /* Use the client requested access mask here, not the one we open with. */
status = open_mode_check(conn, fname, lck,
access_mask, share_access,
create_options, &file_existed);
@@ -1417,6 +1426,8 @@ files_struct *open_file_ntcreate(connection_struct *conn,
(NTCREATEX_OPTIONS_PRIVATE_DENY_DOS|
NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) {
files_struct *fsp_dup;
+
+ /* Use the client requested access mask here, not the one we open with. */
fsp_dup = fcb_or_dos_open(conn, fname, dev,
inode, access_mask,
share_access,
@@ -1532,119 +1543,88 @@ files_struct *open_file_ntcreate(connection_struct *conn,
(unsigned int)flags, (unsigned int)flags2,
(unsigned int)unx_mode));
- /* Drop the lock before doing any real file access. Allows kernel
- oplock breaks to be processed. Handle any races after the open
- call when we re-acquire the lock. */
-
- if (lck) {
- TALLOC_FREE(lck);
- }
-
/*
* open_file strips any O_TRUNC flags itself.
*/
fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode,
- access_mask);
+ access_mask, open_access_mask);
if (!fsp_open) {
+ if (lck != NULL) {
+ TALLOC_FREE(lck);
+ }
file_free(fsp);
return NULL;
}
- /*
- * Deal with the race condition where two smbd's detect the
- * file doesn't exist and do the create at the same time. One
- * of them will win and set a share mode, the other (ie. this
- * one) should check if the requested share mode for this
- * create is allowed.
- */
-
- /*
- * Now the file exists and fsp is successfully opened,
- * fsp->dev and fsp->inode are valid and should replace the
- * dev=0,inode=0 from a non existent file. Spotted by
- * Nadav Danieli <nadavd@exanet.com>. JRA.
- */
-
- dev = fsp->dev;
- inode = fsp->inode;
+ if (!file_existed) {
- lck = get_share_mode_lock(NULL, dev, inode,
- conn->connectpath,
- fname);
+ /*
+ * Deal with the race condition where two smbd's detect the
+ * file doesn't exist and do the create at the same time. One
+ * of them will win and set a share mode, the other (ie. this
+ * one) should check if the requested share mode for this
+ * create is allowed.
+ */
- if (lck == NULL) {
- DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname));
- fd_close(conn, fsp);
- file_free(fsp);
- set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION);
- return NULL;
- }
+ /*
+ * Now the file exists and fsp is successfully opened,
+ * fsp->dev and fsp->inode are valid and should replace the
+ * dev=0,inode=0 from a non existent file. Spotted by
+ * Nadav Danieli <nadavd@exanet.com>. JRA.
+ */
- /*
- * The share entry is again *locked*.....
- */
+ dev = fsp->dev;
+ inode = fsp->inode;
- /* First pass - send break only on batch oplocks. */
- if (delay_for_oplocks(lck, fsp, 1, oplock_request)) {
- schedule_defer_open(lck, request_time);
- fd_close(conn, fsp);
- file_free(fsp);
- TALLOC_FREE(lck);
- set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION);
- return NULL;
- }
-
- status = open_mode_check(conn, fname, lck,
- access_mask, share_access,
- create_options, &file_existed);
+ lck = get_share_mode_lock(NULL, dev, inode,
+ conn->connectpath,
+ fname);
- if (NT_STATUS_IS_OK(status)) {
- /* We might be going to allow this open. Check oplock status again. */
- /* Second pass - send break for both batch or exclusive oplocks. */
- if (delay_for_oplocks(lck, fsp, 2, oplock_request)) {
- schedule_defer_open(lck, request_time);
+ if (lck == NULL) {
+ DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname));
fd_close(conn, fsp);
file_free(fsp);
- TALLOC_FREE(lck);
set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION);
return NULL;
}
- }
- if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) {
- /* DELETE_PENDING is not deferred for a second */
- fd_close(conn, fsp);
- file_free(fsp);
- TALLOC_FREE(lck);
- set_saved_ntstatus(status);
- return NULL;
- }
+ status = open_mode_check(conn, fname, lck,
+ access_mask, share_access,
+ create_options, &file_existed);
- if (!NT_STATUS_IS_OK(status)) {
- struct deferred_open_record state;
+ if (!NT_STATUS_IS_OK(status)) {
+ struct deferred_open_record state;
- fd_close(conn, fsp);
- file_free(fsp);
+ fd_close(conn, fsp);
+ file_free(fsp);
- state.delayed_for_oplocks = False;
- state.dev = dev;
- state.inode = inode;
+ state.delayed_for_oplocks = False;
+ state.dev = dev;
+ state.inode = inode;
- /* Do it all over again immediately. In the second
- * round we will find that the file existed and handle
- * the DELETE_PENDING and FCB cases correctly. No need
- * to duplicate the code here. Essentially this is a
- * "goto top of this function", but don't tell
- * anybody... */
+ /* Do it all over again immediately. In the second
+ * round we will find that the file existed and handle
+ * the DELETE_PENDING and FCB cases correctly. No need
+ * to duplicate the code here. Essentially this is a
+ * "goto top of this function", but don't tell
+ * anybody... */
+
+ defer_open(lck, request_time, timeval_zero(),
+ &state);
+ TALLOC_FREE(lck);
+ return NULL;
+ }
+
+ /*
+ * We exit this block with the share entry *locked*.....
+ */
- defer_open(lck, request_time, timeval_zero(),
- &state);
- TALLOC_FREE(lck);
- return NULL;
}
+ SMB_ASSERT(lck != NULL);
+
/* note that we ignore failure for the following. It is
basically a hack for NFS, and NFS will never set one of
these only read them. Nobody but Samba can ever set a deny
@@ -1685,7 +1665,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
if (file_existed) {
/* stat opens on existing files don't get oplocks. */
- if (is_stat_open(fsp->access_mask)) {
+ if (is_stat_open(open_access_mask)) {
fsp->oplock_type = NO_OPLOCK;
}
@@ -1828,7 +1808,7 @@ files_struct *open_file_fchmod(connection_struct *conn, const char *fname,
/* note! we must use a non-zero desired access or we don't get
a real file descriptor. Oh what a twisted web we weave. */
- fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA);
+ fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA,FILE_WRITE_DATA);
/*
* This is not a user visible file open.
diff --git a/source/utils/net_ads.c b/source/utils/net_ads.c
index 5e84f229aa2..31a6b80912a 100644
--- a/source/utils/net_ads.c
+++ b/source/utils/net_ads.c
@@ -24,22 +24,6 @@
#include "includes.h"
#include "utils/net.h"
-/* Macro for checking RPC error codes to make things more readable */
-
-#if 0
-#define CHECK_RPC_ERR(rpc, msg) \
- if (!NT_STATUS_IS_OK(result = rpc)) { \
- DEBUG(0, (msg ": %s\n", nt_errstr(result))); \
- goto done; \
- }
-
-#define CHECK_RPC_ERR_DEBUG(rpc, debug_args) \
- if (!NT_STATUS_IS_OK(result = rpc)) { \
- DEBUG(0, debug_args); \
- goto done; \
- }
-
-#endif
#ifdef HAVE_ADS
int net_ads_usage(int argc, const char **argv)
@@ -944,7 +928,7 @@ done:
static ADS_STATUS net_set_machine_spn(TALLOC_CTX *ctx, ADS_STRUCT *ads_s )
{
ADS_STATUS status = ADS_ERROR(LDAP_SERVER_DOWN);
- char *host_upn, *new_dn;
+ char *new_dn;
ADS_MODLIST mods;
const char *servicePrincipalName[3] = {NULL, NULL, NULL};
char *psp;
@@ -980,9 +964,7 @@ static ADS_STATUS net_set_machine_spn(TALLOC_CTX *ctx, ADS_STRUCT *ads_s )
return ADS_ERROR(LDAP_NO_MEMORY);
}
- /* Windows only creates HOST/shortname & HOST/fqdn. We create
- the UPN as well so that 'kinit -k' will work. You can only
- request a TGT for entries with a UPN in AD. */
+ /* Windows only creates HOST/shortname & HOST/fqdn. */
if ( !(psp = talloc_asprintf(ctx, "HOST/%s", machine_name)) )
goto done;
@@ -995,9 +977,63 @@ static ADS_STATUS net_set_machine_spn(TALLOC_CTX *ctx, ADS_STRUCT *ads_s )
goto done;
servicePrincipalName[1] = psp;
- if (!(host_upn = talloc_asprintf(ctx, "%s@%s", servicePrincipalName[0], ads_s->config.realm)))
+ if (!(mods = ads_init_mods(ctx))) {
goto done;
+ }
+
+ /* fields of primary importance */
+
+ ads_mod_str(ctx, &mods, "dNSHostName", my_fqdn);
+ ads_mod_strlist(ctx, &mods, "servicePrincipalName", servicePrincipalName);
+
+ status = ads_gen_mod(ads_s, new_dn, mods);
+
+done:
+ ads_msgfree(ads_s, res);
+
+ return status;
+}
+
+/*******************************************************************
+ Set a machines dNSHostName and servicePrincipalName attributes
+ ********************************************************************/
+static ADS_STATUS net_set_machine_upn(TALLOC_CTX *ctx, ADS_STRUCT *ads_s, const char *upn )
+{
+ ADS_STATUS status = ADS_ERROR(LDAP_SERVER_DOWN);
+ char *new_dn;
+ ADS_MODLIST mods;
+ LDAPMessage *res = NULL;
+ char *dn_string = NULL;
+ const char *machine_name = global_myname();
+ int count;
+
+ if ( !machine_name ) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ /* Find our DN */
+
+ status = ads_find_machine_acct(ads_s, (void **)(void *)&res, machine_name);
+ if (!ADS_ERR_OK(status))
+ return status;
+
+ if ( (count = ads_count_replies(ads_s, res)) != 1 ) {
+ DEBUG(1,("net_set_machine_spn: %d entries returned!\n", count));
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ if ( (dn_string = ads_get_dn(ads_s, res)) == NULL ) {
+ DEBUG(1, ("ads_add_machine_acct: ads_get_dn returned NULL (malloc failure?)\n"));
+ goto done;
+ }
+
+ new_dn = talloc_strdup(ctx, dn_string);
+ ads_memfree(ads_s, dn_string);
+ if (!new_dn) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
/* now do the mods */
if (!(mods = ads_init_mods(ctx))) {
@@ -1006,8 +1042,7 @@ static ADS_STATUS net_set_machine_spn(TALLOC_CTX *ctx, ADS_STRUCT *ads_s )
/* fields of primary importance */
- ads_mod_str(ctx, &mods, "dNSHostName", my_fqdn);
- ads_mod_strlist(ctx, &mods, "servicePrincipalName", servicePrincipalName);
+ ads_mod_str(ctx, &mods, "userPrincipalName", upn);
status = ads_gen_mod(ads_s, new_dn, mods);
@@ -1017,7 +1052,6 @@ done:
return status;
}
-
/*******************************************************************
join a domain using ADS (LDAP mods)
********************************************************************/
@@ -1105,6 +1139,19 @@ static BOOL net_derive_salting_principal( TALLOC_CTX *ctx, ADS_STRUCT *ads )
return kerberos_secrets_store_des_salt( salt );
}
+/*********************************************************
+ utility function to parse an integer parameter from
+ "parameter = value"
+**********************************************************/
+static char* get_string_param( const char* param )
+{
+ char *p;
+
+ if ( (p = strchr( param, '=' )) == NULL )
+ return NULL;
+
+ return (p+1);
+}
/*******************************************************************
join a domain using ADS (LDAP mods)
********************************************************************/
@@ -1119,6 +1166,10 @@ int net_ads_join(int argc, const char **argv)
struct cldap_netlogon_reply cldap_reply;
TALLOC_CTX *ctx;
DOM_SID *domain_sid = NULL;
+ BOOL createupn = False;
+ const char *machineupn = NULL;
+ const char *create_in_ou = NULL;
+ int i;
if ( check_ads_config() != 0 ) {
d_fprintf(stderr, "Invalid configuration. Exiting....\n");
@@ -1142,11 +1193,30 @@ int net_ads_join(int argc, const char **argv)
return -1;
}
- /* If we were given an OU, try to create the machine in the OU account
- first and then do the normal RPC join */
+ /* process additional command line args */
+
+ for ( i=0; i<argc; i++ ) {
+ if ( !StrnCaseCmp(argv[i], "createupn", strlen("createupn")) ) {
+ createupn = True;
+ machineupn = get_string_param(argv[i]);
+ }
+ else if ( !StrnCaseCmp(argv[i], "createcomputer", strlen("createcomputer")) ) {
+ if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
+ d_fprintf(stderr, "Please supply a valid OU path\n");
+ return -1;
+ }
+ }
+ else {
+ d_fprintf(stderr, "Bad option: %s\n", argv[i]);
+ return -1;
+ }
+ }
- if ( argc > 0 ) {
- status = net_precreate_machine_acct( ads, argv[0] );
+ /* If we were given an OU, try to create the machine in
+ the OU account first and then do the normal RPC join */
+
+ if ( create_in_ou ) {
+ status = net_precreate_machine_acct( ads, create_in_ou );
if ( !ADS_ERR_OK(status) ) {
d_fprintf( stderr, "Failed to pre-create the machine object "
"in OU %s.\n", argv[0]);
@@ -1208,11 +1278,24 @@ int net_ads_join(int argc, const char **argv)
status = net_set_machine_spn( ctx, ads );
if ( !ADS_ERR_OK(status) ) {
- d_fprintf(stderr, "Failed to set servicePrincipalNames. Only NTLM authentication will be possible.\n");
- d_fprintf(stderr, "Please ensure that the DNS domain of this server matches the AD domain,\n");
- d_fprintf(stderr, "Or rejoin with using Domain Admin credentials.\n");
- /* don't fail */
+ d_fprintf(stderr, "Failed to set servicePrincipalNames. Please ensure that\n");
+ d_fprintf(stderr, "the DNS domain of this server matches the AD domain,\n");
+ d_fprintf(stderr, "Or rejoin with using Domain Admin credentials.\n");
+
+ /* Disable the machine account in AD. Better to fail than to leave
+ a confused admin. */
+
+ if ( net_ads_leave( 0, NULL ) != 0 ) {
+ d_fprintf( stderr, "Failed to disable machine account in AD. Please do so manually.\n");
+ }
+
+ /* clear out the machine password */
+
+ netdom_store_machine_account( lp_workgroup(), domain_sid, "" );
+ netdom_store_machine_account( short_domain_name, domain_sid, "" );
+
+ return -1;
}
if ( !net_derive_salting_principal( ctx, ads ) ) {
@@ -1221,6 +1304,22 @@ int net_ads_join(int argc, const char **argv)
return -1;
}
+ if ( createupn ) {
+ pstring upn;
+
+ /* default to using the short UPN name */
+ if ( !machineupn ) {
+ snprintf( upn, sizeof(upn), "host/%s@%s", global_myname(),
+ ads->config.realm );
+ machineupn = upn;
+ }
+
+ status = net_set_machine_upn( ctx, ads, machineupn );
+ if ( !ADS_ERR_OK(status) ) {
+ d_fprintf(stderr, "Failed to set userPrincipalName. Are you a Domain Admin?\n");
+ }
+ }
+
/* Now build the keytab, using the same ADS connection */
if (lp_use_kerberos_keytab() && ads_keytab_create_default(ads)) {
DEBUG(1,("Error creating host keytab!\n"));
@@ -1891,15 +1990,12 @@ int net_ads_help(int argc, const char **argv)
{"GROUP", net_ads_group_usage},
{"PRINTER", net_ads_printer_usage},
{"SEARCH", net_ads_search_usage},
-#if 0
{"INFO", net_ads_info},
{"JOIN", net_ads_join},
- {"JOIN2", net_ads_join2},
{"LEAVE", net_ads_leave},
{"STATUS", net_ads_status},
{"PASSWORD", net_ads_password},
{"CHANGETRUSTPW", net_ads_changetrustpw},
-#endif
{NULL, NULL}
};
@@ -1991,4 +2087,4 @@ int net_ads(int argc, const char **argv)
return net_ads_usage(argc, argv);
}
-#endif
+#endif /* WITH_ADS */