mirror of
https://github.com/samba-team/samba.git
synced 2024-12-21 09:34:19 +03:00
Compare commits
54 Commits
86cdaf5a2e
...
e0aab377bd
Author | SHA1 | Date | |
---|---|---|---|
|
e0aab377bd | ||
|
890724f8a5 | ||
|
bf20ec9642 | ||
|
e97fbcc4b1 | ||
|
2e8009b4ca | ||
|
e52873766e | ||
|
a7d8d80179 | ||
|
04977dbb67 | ||
|
83f7129e58 | ||
|
663f03996c | ||
|
cf69a9ef14 | ||
|
671186d8f6 | ||
|
f29b06760a | ||
|
9afd9fc7da | ||
|
6262f9a66e | ||
|
719d4f98c4 | ||
|
6098724e8b | ||
|
e166299b18 | ||
|
e1767db3db | ||
|
6b7ca29ffb | ||
|
7116dca925 | ||
|
be20007cc7 | ||
|
c1b9dc9f7a | ||
|
3035f98364 | ||
|
de8babd6af | ||
|
d745a0799b | ||
|
aff7a1fde6 | ||
|
ee3a7b31e0 | ||
|
253e5f4a68 | ||
|
06cca7bf02 | ||
|
69d74563ad | ||
|
2d6d890f45 | ||
|
3a16c35ab4 | ||
|
b768c54bd5 | ||
|
a780c07c24 | ||
|
f41dc1440b | ||
|
84faa9dbb4 | ||
|
ddc88fa8b6 | ||
|
9312bdd271 | ||
|
d6ec1f42c6 | ||
|
391962e262 | ||
|
dddbab8e36 | ||
|
8f1d903524 | ||
|
d088738342 | ||
|
54124677f6 | ||
|
3b2134e231 | ||
|
8ed1b9e874 | ||
|
e37e4d16e9 | ||
|
02d4f58a2f | ||
|
94c9a99c56 | ||
|
1a089a16c4 | ||
|
0a9adc85e7 | ||
|
0a5da82f75 | ||
|
7b73c574d9 |
@ -1548,12 +1548,33 @@ to show in the result.
|
||||
<title>ADS KEYTAB <replaceable>CREATE</replaceable></title>
|
||||
|
||||
<para>
|
||||
Creates a new keytab file if one doesn't exist with default entries. Default
|
||||
entries are kerberos principals created from the machinename of the
|
||||
client, the UPN (if it exists) and any Windows SPN(s) associated with the
|
||||
computer AD account for the client. If a keytab file already exists then only
|
||||
missing kerberos principals from the default entries are added. No changes
|
||||
are made to the computer AD account.
|
||||
Since Samba 4.21.0, keytab file is created as specified in <smbconfoption
|
||||
name="sync machine password to keytab"/>. The keytab is created only for
|
||||
<smbconfoption name="kerberos method">secrets only</smbconfoption> and
|
||||
<smbconfoption name="kerberos method">secrets and keytab</smbconfoption>. With
|
||||
the smb.conf default values for <smbconfoption name="kerberos method"> secrets
|
||||
only</smbconfoption> and <smbconfoption name="sync machine password to keytab"/>
|
||||
(default is empty) the keytab is not generated at all. Keytab with a default
|
||||
name and SPNs synced from AD is created for <smbconfoption name="kerberos
|
||||
method">secrets and keytab</smbconfoption> if <smbconfoption name="sync machine
|
||||
password to keytab"/> is missing.
|
||||
</para>
|
||||
<para>
|
||||
Till Samba 4.20.0, two more entries were created by default: the machinename of
|
||||
the client (ending with '$') and the UPN (host/domain@REALM). If these two
|
||||
entries are still needed, each must be specified in an own keytab file.
|
||||
Example below will generate three keytab files that contain SPNs synced from
|
||||
AD, host UPN and machine$ SPN:
|
||||
</para>
|
||||
<programlisting>
|
||||
<smbconfoption name="sync machine password to keytab">
|
||||
/etc/krb5.keytab0:sync_spns:machine_password,
|
||||
/etc/krb5.keytab1:spns=host/smb.com@SMB.COM:machine_password,
|
||||
/etc/krb5.keytab2:account_name:machine_password
|
||||
</smbconfoption>
|
||||
</programlisting>
|
||||
<para>
|
||||
No changes are made to the computer AD account.
|
||||
</para>
|
||||
</refsect2>
|
||||
|
||||
|
@ -62,7 +62,10 @@
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>This module is stackable.</para>
|
||||
<para> This module is not fully stackable. It can be combined with other
|
||||
modules, but should be the last module in the <command>vfs objects</command>
|
||||
list. It directly access the files in the OS filesystem.
|
||||
</para>
|
||||
|
||||
</refsect1>
|
||||
|
||||
|
@ -62,7 +62,6 @@
|
||||
<arg choice="opt">--remove-uid-mapping uid,sid</arg>
|
||||
<arg choice="opt">-s sid</arg>
|
||||
<arg choice="opt">--separator</arg>
|
||||
<arg choice="opt">--sequence</arg>
|
||||
<arg choice="opt">--set-auth-user user%password</arg>
|
||||
<arg choice="opt">--set-gid-mapping gid,sid</arg>
|
||||
<arg choice="opt">--set-uid-mapping uid,sid</arg>
|
||||
@ -458,13 +457,6 @@
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>--sequence</term>
|
||||
<listitem><para>This command has been deprecated. Please use
|
||||
the --online-status option instead.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>--set-auth-user <replaceable>username%password</replaceable></term>
|
||||
<listitem><para>Store username and password used by <citerefentry>
|
||||
|
@ -245,8 +245,9 @@ static uint32_t access_check_max_allowed(const struct security_descriptor *sd,
|
||||
if (security_token_has_sid(token, sd->owner_sid)) {
|
||||
switch (implicit_owner_rights) {
|
||||
case IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS:
|
||||
granted |= SEC_STD_WRITE_DAC;
|
||||
FALL_THROUGH;
|
||||
granted |= (SEC_STD_READ_CONTROL |
|
||||
SEC_STD_WRITE_DAC);
|
||||
break;
|
||||
case IMPLICIT_OWNER_READ_CONTROL_RIGHTS:
|
||||
granted |= SEC_STD_READ_CONTROL;
|
||||
break;
|
||||
@ -282,8 +283,8 @@ static uint32_t access_check_max_allowed(const struct security_descriptor *sd,
|
||||
if (am_owner && !have_owner_rights_ace) {
|
||||
switch (implicit_owner_rights) {
|
||||
case IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS:
|
||||
granted |= SEC_STD_WRITE_DAC;
|
||||
FALL_THROUGH;
|
||||
granted |= (SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC);
|
||||
break;
|
||||
case IMPLICIT_OWNER_READ_CONTROL_RIGHTS:
|
||||
granted |= SEC_STD_READ_CONTROL;
|
||||
break;
|
||||
@ -436,8 +437,9 @@ static NTSTATUS se_access_check_implicit_owner(const struct security_descriptor
|
||||
if (am_owner && !have_owner_rights_ace) {
|
||||
switch (implicit_owner_rights) {
|
||||
case IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS:
|
||||
bits_remaining &= ~SEC_STD_WRITE_DAC;
|
||||
FALL_THROUGH;
|
||||
bits_remaining &= ~(SEC_STD_WRITE_DAC |
|
||||
SEC_STD_READ_CONTROL);
|
||||
break;
|
||||
case IMPLICIT_OWNER_READ_CONTROL_RIGHTS:
|
||||
bits_remaining &= ~SEC_STD_READ_CONTROL;
|
||||
break;
|
||||
@ -596,10 +598,10 @@ NTSTATUS se_file_access_check(const struct security_descriptor *sd,
|
||||
access_desired |= SEC_RIGHTS_PRIV_RESTORE;
|
||||
}
|
||||
|
||||
DEBUG(10,("se_file_access_check: MAX desired = 0x%x "
|
||||
"mapped to 0x%x\n",
|
||||
orig_access_desired,
|
||||
access_desired));
|
||||
DBG_DEBUG("MAX desired = 0x%0" PRIx32 " mapped to 0x%" PRIx32
|
||||
"\n ",
|
||||
orig_access_desired,
|
||||
access_desired);
|
||||
}
|
||||
|
||||
status = se_access_check_implicit_owner(sd,
|
||||
@ -751,8 +753,9 @@ NTSTATUS sec_access_check_ds_implicit_owner(const struct security_descriptor *sd
|
||||
security_token_has_sid(token, sd->owner_sid)) {
|
||||
switch (implicit_owner_rights) {
|
||||
case IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS:
|
||||
bits_remaining &= ~SEC_STD_WRITE_DAC;
|
||||
FALL_THROUGH;
|
||||
bits_remaining &= ~(SEC_STD_WRITE_DAC |
|
||||
SEC_STD_READ_CONTROL);
|
||||
break;
|
||||
case IMPLICIT_OWNER_READ_CONTROL_RIGHTS:
|
||||
bits_remaining &= ~SEC_STD_READ_CONTROL;
|
||||
break;
|
||||
|
@ -109,26 +109,23 @@ static bool check_integer_range(const struct ace_condition_token *tok)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t pull_integer(TALLOC_CTX *mem_ctx,
|
||||
uint8_t *data, size_t length,
|
||||
struct ace_condition_int *tok)
|
||||
static ssize_t pull_integer(uint8_t *data,
|
||||
size_t length,
|
||||
struct ace_condition_int *tok)
|
||||
{
|
||||
ssize_t bytes_used;
|
||||
size_t consumed;
|
||||
enum ndr_err_code ndr_err;
|
||||
DATA_BLOB v = data_blob_const(data, length);
|
||||
struct ndr_pull *ndr = ndr_pull_init_blob(&v, mem_ctx);
|
||||
if (ndr == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ndr_err = ndr_pull_ace_condition_int(ndr, NDR_SCALARS|NDR_BUFFERS, tok);
|
||||
|
||||
ndr_err = ndr_pull_struct_blob_noalloc(
|
||||
data,
|
||||
length,
|
||||
tok,
|
||||
(ndr_pull_flags_fn_t)ndr_pull_ace_condition_int,
|
||||
&consumed);
|
||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||
TALLOC_FREE(ndr);
|
||||
return -1;
|
||||
}
|
||||
bytes_used = ndr->offset;
|
||||
TALLOC_FREE(ndr);
|
||||
return bytes_used;
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static ssize_t push_integer(uint8_t *data, size_t available,
|
||||
@ -335,8 +332,7 @@ static ssize_t pull_composite(TALLOC_CTX *mem_ctx,
|
||||
case CONDITIONAL_ACE_TOKEN_INT16:
|
||||
case CONDITIONAL_ACE_TOKEN_INT32:
|
||||
case CONDITIONAL_ACE_TOKEN_INT64:
|
||||
consumed = pull_integer(mem_ctx,
|
||||
el_data,
|
||||
consumed = pull_integer(el_data,
|
||||
available,
|
||||
&el->data.int64);
|
||||
ok = check_integer_range(el);
|
||||
@ -507,7 +503,7 @@ static ssize_t pull_end_padding(uint8_t *data, size_t length)
|
||||
*
|
||||
* zero is also called CONDITIONAL_ACE_TOKEN_INVALID_OR_PADDING.
|
||||
*/
|
||||
ssize_t i;
|
||||
size_t i;
|
||||
if (length > 2) {
|
||||
return -1;
|
||||
}
|
||||
@ -592,8 +588,7 @@ struct ace_condition_script *parse_conditional_ace(TALLOC_CTX *mem_ctx,
|
||||
case CONDITIONAL_ACE_TOKEN_INT16:
|
||||
case CONDITIONAL_ACE_TOKEN_INT32:
|
||||
case CONDITIONAL_ACE_TOKEN_INT64:
|
||||
consumed = pull_integer(program,
|
||||
tok_data,
|
||||
consumed = pull_integer(tok_data,
|
||||
available,
|
||||
&tok->data.int64);
|
||||
ok = check_integer_range(tok);
|
||||
|
@ -110,20 +110,18 @@ void display_sec_ace_flags(uint8_t flags)
|
||||
****************************************************************************/
|
||||
static void disp_sec_ace_object(struct security_ace_object *object)
|
||||
{
|
||||
char *str;
|
||||
struct GUID_txt_buf buf;
|
||||
|
||||
if (object->flags & SEC_ACE_OBJECT_TYPE_PRESENT) {
|
||||
str = GUID_string(NULL, &object->type.type);
|
||||
if (str == NULL) return;
|
||||
printf("Object type: SEC_ACE_OBJECT_TYPE_PRESENT\n");
|
||||
printf("Object GUID: %s\n", str);
|
||||
talloc_free(str);
|
||||
printf("Object GUID: %s\n",
|
||||
GUID_buf_string(&object->type.type, &buf));
|
||||
}
|
||||
if (object->flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT) {
|
||||
str = GUID_string(NULL, &object->inherited_type.inherited_type);
|
||||
if (str == NULL) return;
|
||||
printf("Object type: SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT\n");
|
||||
printf("Object GUID: %s\n", str);
|
||||
talloc_free(str);
|
||||
printf("Object GUID: %s\n",
|
||||
GUID_buf_string(&object->inherited_type.inherited_type,
|
||||
&buf));
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,8 +184,9 @@ void display_sec_acl(struct security_acl *sec_acl)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
printf("\tACL\tNum ACEs:\t%u\trevision:\t%x\n",
|
||||
sec_acl->num_aces, sec_acl->revision);
|
||||
printf("\tACL\tNum ACEs:\t%" PRIu32 "\trevision:\t%x\n",
|
||||
sec_acl->num_aces,
|
||||
sec_acl->revision);
|
||||
printf("\t---\n");
|
||||
|
||||
if (sec_acl->size != 0 && sec_acl->num_aces != 0) {
|
||||
|
@ -298,7 +298,8 @@ static NTSTATUS security_descriptor_acl_add(struct security_descriptor *sd,
|
||||
|
||||
if (idx < 0) {
|
||||
return NT_STATUS_ARRAY_BOUNDS_EXCEEDED;
|
||||
} else if (idx > acl->num_aces) {
|
||||
}
|
||||
if (idx > acl->num_aces) {
|
||||
return NT_STATUS_ARRAY_BOUNDS_EXCEEDED;
|
||||
}
|
||||
|
||||
|
@ -51,52 +51,27 @@ struct security_token *security_token_initialise(TALLOC_CTX *mem_ctx,
|
||||
|
||||
struct security_token *security_token_duplicate(TALLOC_CTX *mem_ctx, const struct security_token *src)
|
||||
{
|
||||
TALLOC_CTX *frame = NULL;
|
||||
struct security_token *dst = NULL;
|
||||
DATA_BLOB blob;
|
||||
enum ndr_err_code ndr_err;
|
||||
|
||||
if (src == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
frame = talloc_stackframe();
|
||||
|
||||
ndr_err = ndr_push_struct_blob(
|
||||
&blob,
|
||||
frame,
|
||||
src,
|
||||
(ndr_push_flags_fn_t)ndr_push_security_token);
|
||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||
DBG_ERR("Failed to duplicate security_token ndr_push_security_token failed: %s\n",
|
||||
ndr_errstr(ndr_err));
|
||||
TALLOC_FREE(frame);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dst = talloc_zero(mem_ctx, struct security_token);
|
||||
if (dst == NULL) {
|
||||
DBG_ERR("talloc failed\n");
|
||||
TALLOC_FREE(frame);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ndr_err = ndr_pull_struct_blob(
|
||||
&blob,
|
||||
dst,
|
||||
dst,
|
||||
(ndr_pull_flags_fn_t)ndr_pull_security_token);
|
||||
|
||||
ndr_err = ndr_deepcopy_struct(security_token, src, dst, dst);
|
||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||
DBG_ERR("Failed to duplicate security_token ndr_pull_security_token "
|
||||
"failed: %s\n",
|
||||
DBG_ERR("Failed to duplicate security_token: %s\n",
|
||||
ndr_errstr(ndr_err));
|
||||
TALLOC_FREE(dst);
|
||||
TALLOC_FREE(frame);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TALLOC_FREE(frame);
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
@ -323,16 +323,17 @@ bool sid_peek_check_rid(const struct dom_sid *exp_dom_sid, const struct dom_sid
|
||||
|
||||
void sid_copy(struct dom_sid *dst, const struct dom_sid *src)
|
||||
{
|
||||
int i;
|
||||
const int8_t num_auths = MIN(15, MAX(0, src->num_auths));
|
||||
int8_t i;
|
||||
|
||||
*dst = (struct dom_sid) {
|
||||
.sid_rev_num = src->sid_rev_num,
|
||||
.num_auths = src->num_auths,
|
||||
.num_auths = num_auths,
|
||||
};
|
||||
|
||||
memcpy(&dst->id_auth[0], &src->id_auth[0], sizeof(src->id_auth));
|
||||
|
||||
for (i = 0; i < src->num_auths; i++)
|
||||
for (i = 0; i < num_auths; i++)
|
||||
dst->sub_auths[i] = src->sub_auths[i];
|
||||
}
|
||||
|
||||
|
@ -36,24 +36,6 @@ testfail()
|
||||
fi
|
||||
}
|
||||
|
||||
knownfail()
|
||||
{
|
||||
name="$1"
|
||||
shift
|
||||
cmdline="$*"
|
||||
echo "test: $name"
|
||||
$cmdline
|
||||
status=$?
|
||||
if [ x$status = x0 ]; then
|
||||
echo "failure: $name [unexpected success]"
|
||||
status=1
|
||||
else
|
||||
echo "knownfail: $name"
|
||||
status=0
|
||||
fi
|
||||
return $status
|
||||
}
|
||||
|
||||
KRB5CCNAME_PATH="$PREFIX/test_wbinfo_krb5ccache"
|
||||
rm -f $KRB5CCNAME_PATH
|
||||
|
||||
@ -218,9 +200,6 @@ else
|
||||
failed=$(expr $failed + 1)
|
||||
fi
|
||||
|
||||
# this does not work
|
||||
knownfail "wbinfo --sequence against $TARGET" $wbinfo --sequence
|
||||
|
||||
# this is stubbed out now
|
||||
testit "wbinfo -D against $TARGET" $wbinfo -D $DOMAIN || failed=$(expr $failed + 1)
|
||||
|
||||
|
@ -605,14 +605,6 @@ static bool wbinfo_list_own_domain(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* show sequence numbers */
|
||||
static bool wbinfo_show_sequence(const char *domain)
|
||||
{
|
||||
d_printf("This command has been deprecated. Please use the "
|
||||
"--online-status option instead.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* show sequence numbers */
|
||||
static bool wbinfo_show_onlinestatus(const char *domain)
|
||||
{
|
||||
@ -2295,7 +2287,6 @@ enum {
|
||||
OPT_SET_AUTH_USER = 1000,
|
||||
OPT_GET_AUTH_USER,
|
||||
OPT_DOMAIN_NAME,
|
||||
OPT_SEQUENCE,
|
||||
OPT_GETDCNAME,
|
||||
OPT_DSGETDCNAME,
|
||||
OPT_DC_INFO,
|
||||
@ -2581,12 +2572,6 @@ int main(int argc, const char **argv, char **envp)
|
||||
.val = OPT_LIST_OWN_DOMAIN,
|
||||
.descrip = "List own domain",
|
||||
},
|
||||
{
|
||||
.longName = "sequence",
|
||||
.argInfo = POPT_ARG_NONE,
|
||||
.val = OPT_SEQUENCE,
|
||||
.descrip = "Deprecated command, see --online-status",
|
||||
},
|
||||
{
|
||||
.longName = "online-status",
|
||||
.argInfo = POPT_ARG_NONE,
|
||||
@ -3099,13 +3084,6 @@ int main(int argc, const char **argv, char **envp)
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case OPT_SEQUENCE:
|
||||
if (!wbinfo_show_sequence(opt_domain_name)) {
|
||||
d_fprintf(stderr,
|
||||
"Could not show sequence numbers\n");
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case OPT_ONLINESTATUS:
|
||||
if (!wbinfo_show_onlinestatus(opt_domain_name)) {
|
||||
d_fprintf(stderr,
|
||||
|
@ -63,8 +63,9 @@ typedef char fstring[FSTRING_LEN];
|
||||
* 31: added "client_name" to the request
|
||||
* 32: added "traceid" to the request
|
||||
* removed WINBINDD_INIT_CONNECTION
|
||||
* 33: removed WINBINDD_SHOW_SEQUENCE
|
||||
*/
|
||||
#define WINBIND_INTERFACE_VERSION 32
|
||||
#define WINBIND_INTERFACE_VERSION 33
|
||||
|
||||
/* Have to deal with time_t being 4 or 8 bytes due to structure alignment.
|
||||
On a 64bit Linux box, we have to support a constant structure size
|
||||
@ -141,8 +142,6 @@ enum winbindd_cmd {
|
||||
WINBINDD_DSGETDCNAME, /* Issue a DsGetDCName Request */
|
||||
WINBINDD_DC_INFO, /* Which DC are we connected to? */
|
||||
|
||||
WINBINDD_SHOW_SEQUENCE, /* display sequence numbers of domains */
|
||||
|
||||
/* WINS commands */
|
||||
|
||||
WINBINDD_WINS_BYIP,
|
||||
|
@ -2783,6 +2783,9 @@ sub provision($$)
|
||||
my $recycle_shrdir="$shrdir/recycle";
|
||||
push(@dirs,$recycle_shrdir);
|
||||
|
||||
my $recycle_shrdir2="$shrdir/recycle2";
|
||||
push(@dirs,$recycle_shrdir2);
|
||||
|
||||
my $fakedircreatetimes_shrdir="$shrdir/fakedircreatetimes";
|
||||
push(@dirs,$fakedircreatetimes_shrdir);
|
||||
|
||||
@ -3718,6 +3721,15 @@ sub provision($$)
|
||||
recycle : exclude = *.tmp
|
||||
recycle : directory_mode = 755
|
||||
|
||||
[recycle2]
|
||||
copy = tmp
|
||||
path = $recycle_shrdir2
|
||||
vfs objects = recycle crossrename
|
||||
recycle : repository = .trash
|
||||
recycle : exclude = *.tmp
|
||||
recycle : directory_mode = 755
|
||||
wide links = yes
|
||||
|
||||
[fakedircreatetimes]
|
||||
copy = tmp
|
||||
path = $fakedircreatetimes_shrdir
|
||||
|
@ -2584,11 +2584,8 @@ static struct adouble *ad_get_internal(TALLOC_CTX *ctx,
|
||||
int mode;
|
||||
|
||||
if (fsp != NULL) {
|
||||
if (fsp_is_alternate_stream(fsp)) {
|
||||
smb_fname = fsp->base_fsp->fsp_name;
|
||||
} else {
|
||||
smb_fname = fsp->fsp_name;
|
||||
}
|
||||
struct files_struct *meta_fsp = metadata_fsp(fsp);
|
||||
smb_fname = meta_fsp->fsp_name;
|
||||
}
|
||||
|
||||
DEBUG(10, ("ad_get(%s) called for %s\n",
|
||||
|
@ -274,23 +274,20 @@ static int connect_acl_tdb(struct vfs_handle_struct *handle,
|
||||
|
||||
if (config->ignore_system_acls) {
|
||||
mode_t create_mask = lp_create_mask(SNUM(handle->conn));
|
||||
char *create_mask_str = NULL;
|
||||
|
||||
if ((create_mask & 0666) != 0666) {
|
||||
char create_mask_str[16];
|
||||
|
||||
create_mask |= 0666;
|
||||
create_mask_str = talloc_asprintf(handle, "0%o",
|
||||
create_mask);
|
||||
if (create_mask_str == NULL) {
|
||||
DBG_ERR("talloc_asprintf failed\n");
|
||||
return -1;
|
||||
}
|
||||
snprintf(create_mask_str,
|
||||
sizeof(create_mask_str),
|
||||
"0%o",
|
||||
create_mask);
|
||||
|
||||
DBG_NOTICE("setting 'create mask = %s'\n", create_mask_str);
|
||||
|
||||
lp_do_parameter (SNUM(handle->conn),
|
||||
"create mask", create_mask_str);
|
||||
|
||||
TALLOC_FREE(create_mask_str);
|
||||
}
|
||||
|
||||
DBG_NOTICE("setting 'directory mask = 0777', "
|
||||
|
@ -218,23 +218,21 @@ static int connect_acl_xattr(struct vfs_handle_struct *handle,
|
||||
|
||||
if (config->ignore_system_acls) {
|
||||
mode_t create_mask = lp_create_mask(SNUM(handle->conn));
|
||||
char *create_mask_str = NULL;
|
||||
|
||||
if ((create_mask & 0666) != 0666) {
|
||||
char create_mask_str[16];
|
||||
|
||||
create_mask |= 0666;
|
||||
create_mask_str = talloc_asprintf(handle, "0%o",
|
||||
create_mask);
|
||||
if (create_mask_str == NULL) {
|
||||
DBG_ERR("talloc_asprintf failed\n");
|
||||
return -1;
|
||||
}
|
||||
snprintf(create_mask_str,
|
||||
sizeof(create_mask_str),
|
||||
"0%o",
|
||||
create_mask);
|
||||
|
||||
DBG_NOTICE("setting 'create mask = %s'\n", create_mask_str);
|
||||
|
||||
lp_do_parameter (SNUM(handle->conn),
|
||||
"create mask", create_mask_str);
|
||||
|
||||
TALLOC_FREE(create_mask_str);
|
||||
lp_do_parameter(SNUM(handle->conn),
|
||||
"create mask",
|
||||
create_mask_str);
|
||||
}
|
||||
|
||||
DBG_NOTICE("setting 'directory mask = 0777', "
|
||||
|
@ -54,10 +54,12 @@ static NTSTATUS copy_reg(vfs_handle_struct *handle,
|
||||
struct files_struct *dstfsp,
|
||||
const struct smb_filename *dest)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct smb_filename *full_fname_src = NULL;
|
||||
struct smb_filename *full_fname_dst = NULL;
|
||||
NTSTATUS status = NT_STATUS_OK;
|
||||
int ret;
|
||||
off_t off;
|
||||
int ifd = -1;
|
||||
int ofd = -1;
|
||||
struct timespec ts[2];
|
||||
|
||||
if (!VALID_STAT(source->st)) {
|
||||
status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
|
||||
@ -79,64 +81,105 @@ static NTSTATUS copy_reg(vfs_handle_struct *handle,
|
||||
goto out;
|
||||
}
|
||||
|
||||
full_fname_src = full_path_from_dirfsp_atname(talloc_tos(),
|
||||
srcfsp,
|
||||
source);
|
||||
if (full_fname_src == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
full_fname_dst = full_path_from_dirfsp_atname(talloc_tos(),
|
||||
dstfsp,
|
||||
dest);
|
||||
if (full_fname_dst == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = SMB_VFS_NEXT_UNLINKAT(handle,
|
||||
dstfsp,
|
||||
dest,
|
||||
0);
|
||||
if (ret == -1) {
|
||||
if (ret == -1 && errno != ENOENT) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ifd = openat(fsp_get_pathref_fd(srcfsp),
|
||||
source->base_name,
|
||||
O_RDONLY,
|
||||
0);
|
||||
if (ifd < 0) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ofd = openat(fsp_get_pathref_fd(dstfsp),
|
||||
dest->base_name,
|
||||
O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW,
|
||||
0600);
|
||||
if (ofd < 0) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
off = transfer_file(ifd, ofd, source->st.st_ex_size);
|
||||
if (off == -1) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = fchown(ofd, source->st.st_ex_uid, source->st.st_ex_gid);
|
||||
if (ret == -1 && errno != EPERM) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* copy_internals() takes attribute values from the NTrename call.
|
||||
*
|
||||
* From MS-CIFS:
|
||||
*
|
||||
* "If the attribute is 0x0000, then only normal files are renamed.
|
||||
* If the system file or hidden attributes are specified, then the
|
||||
* rename is inclusive of both special types."
|
||||
* fchown turns off set[ug]id bits for non-root,
|
||||
* so do the chmod last.
|
||||
*/
|
||||
status = copy_internals(talloc_tos(),
|
||||
handle->conn,
|
||||
NULL,
|
||||
srcfsp, /* src_dirfsp */
|
||||
full_fname_src,
|
||||
dstfsp, /* dst_dirfsp */
|
||||
full_fname_dst,
|
||||
FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = SMB_VFS_NEXT_UNLINKAT(handle,
|
||||
srcfsp,
|
||||
source,
|
||||
0);
|
||||
if (ret == -1) {
|
||||
ret = fchmod(ofd, source->st.st_ex_mode & 07777);
|
||||
if (ret == -1 && errno != EPERM) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
/* Try to copy the old file's modtime and access time. */
|
||||
ts[0] = source->st.st_ex_atime;
|
||||
ts[1] = source->st.st_ex_mtime;
|
||||
ret = futimens(ofd, ts);
|
||||
if (ret == -1) {
|
||||
DBG_DEBUG("Updating the time stamp on destinaton '%s' failed "
|
||||
"with '%s'. Rename operation can continue.\n",
|
||||
dest->base_name,
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
ret = close(ifd);
|
||||
if (ret == -1) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto out;
|
||||
}
|
||||
ifd = -1;
|
||||
|
||||
ret = close(ofd);
|
||||
if (ret == -1) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto out;
|
||||
}
|
||||
ofd = -1;
|
||||
|
||||
ret = SMB_VFS_NEXT_UNLINKAT(handle, srcfsp, source, 0);
|
||||
if (ret == -1) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
}
|
||||
|
||||
out:
|
||||
if (ifd != -1) {
|
||||
ret = close(ifd);
|
||||
if (ret == -1) {
|
||||
DBG_DEBUG("Failed to close %s (%d): %s.\n",
|
||||
source->base_name,
|
||||
ifd,
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
if (ofd != -1) {
|
||||
ret = close(ofd);
|
||||
if (ret == -1) {
|
||||
DBG_DEBUG("Failed to close %s (%d): %s.\n",
|
||||
dest->base_name,
|
||||
ofd,
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
TALLOC_FREE(full_fname_src);
|
||||
TALLOC_FREE(full_fname_dst);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -170,6 +213,7 @@ static int crossrename_renameat(vfs_handle_struct *handle,
|
||||
smb_fname_src,
|
||||
dstfsp,
|
||||
smb_fname_dst);
|
||||
result = 0;
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
errno = map_errno_from_nt_status(status);
|
||||
result = -1;
|
||||
|
@ -829,12 +829,6 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
status = openat_pathref_fsp(conn->cwd_fsp, smb_fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
ret = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
status = SMB_VFS_CREATE_FILE(
|
||||
conn, /* conn */
|
||||
NULL, /* req */
|
||||
@ -891,13 +885,6 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
status = openat_pathref_fsp(conn->cwd_fsp, smb_fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DBG_NOTICE("Can't open new file [%s], errno = %d\n",
|
||||
smb_fname_str_dbg(smb_fname), errno);
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
status = SMB_VFS_CREATE_FILE(
|
||||
conn, /* conn */
|
||||
NULL, /* req */
|
||||
@ -1110,15 +1097,6 @@ static uint32_t get_correct_cversion(const struct auth_session_info *session_inf
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
nt_status = openat_pathref_fsp(conn->cwd_fsp, smb_fname);
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
DBG_NOTICE("Can't open file [%s]: %s\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
nt_errstr(nt_status));
|
||||
*perr = WERR_ACCESS_DENIED;
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
nt_status = SMB_VFS_CREATE_FILE(
|
||||
conn, /* conn */
|
||||
NULL, /* req */
|
||||
|
@ -176,8 +176,8 @@ static void display_sam_dom_info_2(struct samr_DomGeneralInformation *general)
|
||||
|
||||
static void display_sam_dom_info_3(struct samr_DomInfo3 *info3)
|
||||
{
|
||||
printf("Force Logoff:\t%d\n",
|
||||
(int)nt_time_to_unix_abs(&info3->force_logoff_time));
|
||||
printf("Force Logoff:\t%" PRIu64 "\n",
|
||||
(uint64_t)nt_time_to_unix_abs(&info3->force_logoff_time));
|
||||
}
|
||||
|
||||
static void display_sam_dom_info_4(struct samr_DomOEMInformation *oem)
|
||||
|
@ -29,7 +29,8 @@ export SAMBA_DEPRECATED_SUPPRESS
|
||||
|
||||
# Define the test environment/filenames.
|
||||
#
|
||||
share_test_dir="$LOCAL_PATH"
|
||||
share_test_dir="$LOCAL_PATH/recycle"
|
||||
share_test_dir2="$LOCAL_PATH/recycle2"
|
||||
|
||||
#
|
||||
# Cleanup function.
|
||||
@ -43,6 +44,13 @@ do_cleanup()
|
||||
rm -f testfile2.tmp
|
||||
rm -rf .trash
|
||||
)
|
||||
(
|
||||
#subshell.
|
||||
cd "$share_test_dir2" || return
|
||||
rm -f testfile3
|
||||
rm -f testfile4.tmp
|
||||
rm -rf .trash
|
||||
)
|
||||
}
|
||||
|
||||
#
|
||||
@ -50,6 +58,25 @@ do_cleanup()
|
||||
#
|
||||
do_cleanup
|
||||
|
||||
# Setup .trash on a different filesystem to test crossrename
|
||||
# /tmp or /dev/shm should provide tmpfs
|
||||
#
|
||||
for T in /tmp /dev/shm
|
||||
do
|
||||
if df --portability --print-type $T 2>/dev/null | grep -q tmpfs; then
|
||||
TRASHDIR=$T
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z $TRASHDIR ]; then
|
||||
echo "No tmpfs filesystem found."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TRASHDIR=$(mktemp -d /$TRASHDIR/.trash_XXXXXX)
|
||||
chmod 0755 $TRASHDIR
|
||||
ln -s $TRASHDIR $share_test_dir2/.trash
|
||||
|
||||
test_recycle()
|
||||
{
|
||||
@ -90,12 +117,61 @@ quit
|
||||
return 0
|
||||
}
|
||||
|
||||
test_recycle_crossrename()
|
||||
{
|
||||
tmpfile=$PREFIX/smbclient_interactive_prompt_commands
|
||||
echo "
|
||||
put $tmpfile testfile3
|
||||
put $tmpfile testfile4.tmp
|
||||
del testfile3
|
||||
del testfile4.tmp
|
||||
quit
|
||||
" > $tmpfile
|
||||
cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/recycle2 -I$SERVER_IP $ADDARGS < $tmpfile 2>&1'
|
||||
eval echo "$cmd"
|
||||
out=$(eval "$cmd")
|
||||
ret=$?
|
||||
rm -f "$tmpfile"
|
||||
|
||||
if [ $ret != 0 ]; then
|
||||
printf "%s\n" "$out"
|
||||
printf "failed recycle smbclient run with error %s\n" "$ret"
|
||||
return 1
|
||||
fi
|
||||
|
||||
test -e "$share_test_dir2/.trash/testfile3" || {
|
||||
printf ".trash/testfile3 expected to exist but does NOT exist\n"
|
||||
return 1
|
||||
}
|
||||
test -e "$share_test_dir2/.trash/testfile4.tmp" && {
|
||||
printf ".trash/testfile4.tmp not expected to exist but DOES exist\n"
|
||||
return 1
|
||||
}
|
||||
deviceid1=`stat -c '%d' "$share_test_dir2/"`
|
||||
deviceid2=`stat -c '%d' "$share_test_dir2/.trash/"`
|
||||
test "$deviceid1=" != "$deviceid2" || {
|
||||
printf ".trash/ should be on a different filesystem!\n"
|
||||
return 1
|
||||
}
|
||||
perm_want=755
|
||||
perm_is=`stat -c '%a' "$share_test_dir2/.trash/"`
|
||||
test "$perm_is" = "$perm_want" || {
|
||||
printf ".trash/ permission should be $perm_want but is $perm_is\n"
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
panic_count_0=$(grep -c PANIC $SMBD_TEST_LOG)
|
||||
|
||||
testit "recycle" \
|
||||
test_recycle ||
|
||||
failed=$((failed + 1))
|
||||
|
||||
testit "recycle_crossrename" \
|
||||
test_recycle_crossrename ||
|
||||
failed=$((failed + 1))
|
||||
|
||||
panic_count_1=$(grep -c PANIC $SMBD_TEST_LOG)
|
||||
|
||||
testit "check_panic" test $panic_count_0 -eq $panic_count_1 || failed=$(expr $failed + 1)
|
||||
@ -103,5 +179,7 @@ testit "check_panic" test $panic_count_0 -eq $panic_count_1 || failed=$(expr $fa
|
||||
#
|
||||
# Cleanup.
|
||||
do_cleanup
|
||||
# Cleanup above only deletes a symlink, delete also /tmp/.trash_XXXXXX dir
|
||||
rm -rf "$TRASHDIR"
|
||||
|
||||
testok "$0" "$failed"
|
||||
|
@ -784,7 +784,7 @@ for env in ["fileserver"]:
|
||||
plantestsuite("samba3.blackbox.force_create_mode", env, [os.path.join(samba3srcdir, "script/tests/test_force_create_mode.sh"), '$SERVER', '$DOMAIN', '$USERNAME', '$PASSWORD', '$PREFIX', env, smbclient3])
|
||||
plantestsuite("samba3.blackbox.dropbox", env, [os.path.join(samba3srcdir, "script/tests/test_dropbox.sh"), '$SERVER', '$DOMAIN', 'gooduser', '$PASSWORD', '$PREFIX', env, smbclient3])
|
||||
plantestsuite("samba3.blackbox.offline", env, [os.path.join(samba3srcdir, "script/tests/test_offline.sh"), '$SERVER', '$SERVER_IP', '$DOMAIN', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/offline', smbclient3])
|
||||
plantestsuite("samba3.blackbox.recycle", env, [os.path.join(samba3srcdir, "script/tests/test_recycle.sh"), '$SERVER', '$SERVER_IP', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/recycle', '$PREFIX', smbclient3])
|
||||
plantestsuite("samba3.blackbox.recycle", env, [os.path.join(samba3srcdir, "script/tests/test_recycle.sh"), '$SERVER', '$SERVER_IP', '$USERNAME', '$PASSWORD', '$LOCAL_PATH', '$PREFIX', smbclient3])
|
||||
plantestsuite("samba3.blackbox.fakedircreatetimes", env, [os.path.join(samba3srcdir, "script/tests/test_fakedircreatetimes.sh"), '$SERVER', '$SERVER_IP', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/fakedircreatetimes', '$PREFIX', smbclient3])
|
||||
plantestsuite("samba3.blackbox.shadow_copy2.NT1", env + "_smb1_done", [os.path.join(samba3srcdir, "script/tests/test_shadow_copy.sh"), '$SERVER', '$SERVER_IP', '$DOMAIN', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/shadow', smbclient3, '-m', 'NT1'])
|
||||
plantestsuite("samba3.blackbox.shadow_copy2.SMB3", env, [os.path.join(samba3srcdir, "script/tests/test_shadow_copy.sh"), '$SERVER', '$SERVER_IP', '$DOMAIN', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/shadow', smbclient3, '-m', 'SMB3'])
|
||||
|
@ -973,15 +973,10 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
|
||||
|
||||
return status;
|
||||
}
|
||||
/****************************************************************************
|
||||
Function used by reply_rmdir to delete an entire directory
|
||||
tree recursively. Return True on ok, False on fail.
|
||||
****************************************************************************/
|
||||
|
||||
NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
|
||||
connection_struct *conn,
|
||||
struct smb_filename *smb_dname)
|
||||
static NTSTATUS recursive_rmdir_fsp(struct files_struct *fsp)
|
||||
{
|
||||
struct connection_struct *conn = fsp->conn;
|
||||
const char *dname = NULL;
|
||||
char *talloced = NULL;
|
||||
struct smb_Dir *dir_hnd = NULL;
|
||||
@ -989,14 +984,7 @@ NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
|
||||
int retval;
|
||||
NTSTATUS status = NT_STATUS_OK;
|
||||
|
||||
SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
|
||||
|
||||
status = OpenDir(talloc_tos(),
|
||||
conn,
|
||||
smb_dname,
|
||||
NULL,
|
||||
0,
|
||||
&dir_hnd);
|
||||
status = OpenDir_from_pathref(talloc_tos(), fsp, NULL, 0, &dir_hnd);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
@ -1005,9 +993,6 @@ NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
|
||||
|
||||
while ((dname = ReadDirName(dir_hnd, &talloced))) {
|
||||
struct smb_filename *atname = NULL;
|
||||
struct smb_filename *smb_dname_full = NULL;
|
||||
char *fullname = NULL;
|
||||
bool do_break = true;
|
||||
int unlink_flags = 0;
|
||||
|
||||
if (ISDOT(dname) || ISDOTDOT(dname)) {
|
||||
@ -1015,56 +1000,56 @@ NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Construct the full name. */
|
||||
fullname = talloc_asprintf(ctx,
|
||||
"%s/%s",
|
||||
smb_dname->base_name,
|
||||
dname);
|
||||
if (!fullname) {
|
||||
atname = synthetic_smb_fname(talloc_tos(),
|
||||
dname,
|
||||
NULL,
|
||||
NULL,
|
||||
dirfsp->fsp_name->twrp,
|
||||
dirfsp->fsp_name->flags);
|
||||
TALLOC_FREE(talloced);
|
||||
dname = NULL;
|
||||
|
||||
if (atname == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto err_break;
|
||||
break;
|
||||
}
|
||||
|
||||
smb_dname_full = synthetic_smb_fname(talloc_tos(),
|
||||
fullname,
|
||||
NULL,
|
||||
NULL,
|
||||
smb_dname->twrp,
|
||||
smb_dname->flags);
|
||||
if (smb_dname_full == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto err_break;
|
||||
{
|
||||
struct name_compare_entry *veto_list = conn->veto_list;
|
||||
|
||||
/*
|
||||
* Sneaky hack to be able to open veto files
|
||||
* with openat_pathref_fsp
|
||||
*/
|
||||
|
||||
conn->veto_list = NULL;
|
||||
status = openat_pathref_fsp_lcomp(
|
||||
dirfsp,
|
||||
atname,
|
||||
UCF_POSIX_PATHNAMES /* no ci fallback */);
|
||||
conn->veto_list = veto_list;
|
||||
}
|
||||
|
||||
if (SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto err_break;
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
TALLOC_FREE(atname);
|
||||
if (NT_STATUS_EQUAL(status,
|
||||
NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
|
||||
/* race between readdir and unlink */
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (smb_dname_full->st.st_ex_mode & S_IFDIR) {
|
||||
status = recursive_rmdir(ctx, conn, smb_dname_full);
|
||||
if (atname->st.st_ex_mode & S_IFDIR) {
|
||||
status = recursive_rmdir_fsp(atname->fsp);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto err_break;
|
||||
TALLOC_FREE(atname);
|
||||
break;
|
||||
}
|
||||
unlink_flags = AT_REMOVEDIR;
|
||||
}
|
||||
|
||||
status = synthetic_pathref(talloc_tos(),
|
||||
dirfsp,
|
||||
dname,
|
||||
NULL,
|
||||
&smb_dname_full->st,
|
||||
smb_dname_full->twrp,
|
||||
smb_dname_full->flags,
|
||||
&atname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto err_break;
|
||||
}
|
||||
|
||||
if (!is_visible_fsp(atname->fsp)) {
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(atname);
|
||||
continue;
|
||||
}
|
||||
@ -1075,25 +1060,34 @@ NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
|
||||
unlink_flags);
|
||||
if (retval != 0) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto err_break;
|
||||
}
|
||||
|
||||
/* Successful iteration. */
|
||||
do_break = false;
|
||||
|
||||
err_break:
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(atname);
|
||||
if (do_break) {
|
||||
TALLOC_FREE(atname);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TALLOC_FREE(atname);
|
||||
}
|
||||
|
||||
TALLOC_FREE(dir_hnd);
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
|
||||
connection_struct *conn,
|
||||
struct smb_filename *smb_dname)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
|
||||
|
||||
status = openat_pathref_fsp(conn->cwd_fsp, smb_dname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = recursive_rmdir_fsp(smb_dname->fsp);
|
||||
return status;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
The internals of the rmdir code - called elsewhere.
|
||||
****************************************************************************/
|
||||
@ -1104,8 +1098,6 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, struct files_struct *fsp)
|
||||
struct smb_filename *smb_dname = fsp->fsp_name;
|
||||
struct smb_filename *parent_fname = NULL;
|
||||
struct smb_filename *at_fname = NULL;
|
||||
const char *dname = NULL;
|
||||
char *talloced = NULL;
|
||||
struct smb_Dir *dir_hnd = NULL;
|
||||
struct files_struct *dirfsp = NULL;
|
||||
int unlink_flags = 0;
|
||||
@ -1179,7 +1171,7 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, struct files_struct *fsp)
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if the only thing in this directory are
|
||||
* Check to see if the only things in this directory are
|
||||
* files non-visible to the client. If not, fail the delete.
|
||||
*/
|
||||
|
||||
@ -1196,271 +1188,18 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, struct files_struct *fsp)
|
||||
|
||||
dirfsp = dir_hnd_fetch_fsp(dir_hnd);
|
||||
|
||||
while ((dname = ReadDirName(dir_hnd, &talloced)) != NULL) {
|
||||
struct smb_filename *smb_dname_full = NULL;
|
||||
struct smb_filename *direntry_fname = NULL;
|
||||
char *fullname = NULL;
|
||||
int retval;
|
||||
|
||||
if (ISDOT(dname) || ISDOTDOT(dname)) {
|
||||
TALLOC_FREE(talloced);
|
||||
continue;
|
||||
}
|
||||
if (IS_VETO_PATH(conn, dname)) {
|
||||
TALLOC_FREE(talloced);
|
||||
continue;
|
||||
}
|
||||
|
||||
fullname = talloc_asprintf(talloc_tos(),
|
||||
"%s/%s",
|
||||
smb_dname->base_name,
|
||||
dname);
|
||||
|
||||
if (fullname == NULL) {
|
||||
TALLOC_FREE(talloced);
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
smb_dname_full = synthetic_smb_fname(talloc_tos(),
|
||||
fullname,
|
||||
NULL,
|
||||
NULL,
|
||||
smb_dname->twrp,
|
||||
smb_dname->flags);
|
||||
if (smb_dname_full == NULL) {
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
retval = SMB_VFS_LSTAT(conn, smb_dname_full);
|
||||
if (retval != 0) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
|
||||
/* Could it be an msdfs link ? */
|
||||
if (lp_host_msdfs() &&
|
||||
lp_msdfs_root(SNUM(conn))) {
|
||||
struct smb_filename *smb_atname;
|
||||
smb_atname = synthetic_smb_fname(talloc_tos(),
|
||||
dname,
|
||||
NULL,
|
||||
&smb_dname_full->st,
|
||||
fsp->fsp_name->twrp,
|
||||
fsp->fsp_name->flags);
|
||||
if (smb_atname == NULL) {
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
if (is_msdfs_link(fsp, smb_atname)) {
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
TALLOC_FREE(smb_atname);
|
||||
DBG_DEBUG("got msdfs link name %s "
|
||||
"- can't delete directory %s\n",
|
||||
dname,
|
||||
fsp_str_dbg(fsp));
|
||||
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||
goto err;
|
||||
}
|
||||
TALLOC_FREE(smb_atname);
|
||||
}
|
||||
|
||||
/* Not a DFS link - could it be a dangling symlink ? */
|
||||
retval = SMB_VFS_STAT(conn, smb_dname_full);
|
||||
if (retval == -1 && (errno == ENOENT || errno == ELOOP)) {
|
||||
/*
|
||||
* Dangling symlink.
|
||||
* Allow delete as "delete veto files = yes"
|
||||
*/
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
continue;
|
||||
}
|
||||
|
||||
DBG_DEBUG("got symlink name %s - "
|
||||
"can't delete directory %s\n",
|
||||
dname,
|
||||
fsp_str_dbg(fsp));
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Not a symlink, get a pathref. */
|
||||
status = synthetic_pathref(talloc_tos(),
|
||||
dirfsp,
|
||||
dname,
|
||||
NULL,
|
||||
&smb_dname_full->st,
|
||||
smb_dname->twrp,
|
||||
smb_dname->flags,
|
||||
&direntry_fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!is_visible_fsp(direntry_fname->fsp)) {
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
TALLOC_FREE(direntry_fname);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* We found a client visible name.
|
||||
* We cannot delete this directory.
|
||||
*/
|
||||
DBG_DEBUG("got name %s - "
|
||||
"can't delete directory %s\n",
|
||||
dname,
|
||||
fsp_str_dbg(fsp));
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
TALLOC_FREE(direntry_fname);
|
||||
status = can_delete_directory_hnd(dir_hnd);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Do a recursive delete. */
|
||||
RewindDir(dir_hnd);
|
||||
|
||||
while ((dname = ReadDirName(dir_hnd, &talloced)) != NULL) {
|
||||
struct smb_filename *direntry_fname = NULL;
|
||||
struct smb_filename *smb_dname_full = NULL;
|
||||
char *fullname = NULL;
|
||||
bool do_break = true;
|
||||
int retval;
|
||||
|
||||
if (ISDOT(dname) || ISDOTDOT(dname)) {
|
||||
TALLOC_FREE(talloced);
|
||||
continue;
|
||||
}
|
||||
|
||||
fullname = talloc_asprintf(ctx,
|
||||
"%s/%s",
|
||||
smb_dname->base_name,
|
||||
dname);
|
||||
|
||||
if (fullname == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto err_break;
|
||||
}
|
||||
|
||||
smb_dname_full = synthetic_smb_fname(talloc_tos(),
|
||||
fullname,
|
||||
NULL,
|
||||
NULL,
|
||||
smb_dname->twrp,
|
||||
smb_dname->flags);
|
||||
if (smb_dname_full == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto err_break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Todo: use SMB_VFS_STATX() once that's available.
|
||||
*/
|
||||
|
||||
retval = SMB_VFS_LSTAT(conn, smb_dname_full);
|
||||
if (retval != 0) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto err_break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We are only dealing with VETO'ed objects
|
||||
* here. If it's a symlink, just delete the
|
||||
* link without caring what it is pointing
|
||||
* to.
|
||||
*/
|
||||
if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
|
||||
direntry_fname = synthetic_smb_fname(talloc_tos(),
|
||||
dname,
|
||||
NULL,
|
||||
&smb_dname_full->st,
|
||||
smb_dname->twrp,
|
||||
smb_dname->flags);
|
||||
if (direntry_fname == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto err_break;
|
||||
}
|
||||
} else {
|
||||
status = synthetic_pathref(talloc_tos(),
|
||||
dirfsp,
|
||||
dname,
|
||||
NULL,
|
||||
&smb_dname_full->st,
|
||||
smb_dname->twrp,
|
||||
smb_dname->flags,
|
||||
&direntry_fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto err_break;
|
||||
}
|
||||
|
||||
if (!is_visible_fsp(direntry_fname->fsp)) {
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(direntry_fname);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
unlink_flags = 0;
|
||||
|
||||
if (smb_dname_full->st.st_ex_mode & S_IFDIR) {
|
||||
status = recursive_rmdir(ctx, conn, smb_dname_full);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto err_break;
|
||||
}
|
||||
unlink_flags = AT_REMOVEDIR;
|
||||
}
|
||||
|
||||
retval = SMB_VFS_UNLINKAT(conn,
|
||||
dirfsp,
|
||||
direntry_fname,
|
||||
unlink_flags);
|
||||
if (retval != 0) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto err_break;
|
||||
}
|
||||
|
||||
/* Successful iteration. */
|
||||
do_break = false;
|
||||
|
||||
err_break:
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(direntry_fname);
|
||||
if (do_break) {
|
||||
break;
|
||||
}
|
||||
status = recursive_rmdir_fsp(dirfsp);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* If we get here, we know NT_STATUS_IS_OK(status) */
|
||||
SMB_ASSERT(NT_STATUS_IS_OK(status));
|
||||
|
||||
/* Retry the rmdir */
|
||||
ret = SMB_VFS_UNLINKAT(conn,
|
||||
parent_fname->fsp,
|
||||
|
@ -1222,11 +1222,12 @@ const char *ReadDirName(struct smb_Dir *dir_hnd, char **ptalloced)
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* ignore tmp directories, see mkdir_internals()
|
||||
* ignore tmp directories, see mkdir_internal()
|
||||
*/
|
||||
if (IS_SMBD_TMPNAME(n, &unlink_flags)) {
|
||||
struct files_struct *dirfsp = dir_hnd->fsp;
|
||||
const char *dirname = dirfsp->fsp_name->base_name;
|
||||
struct smb_filename *atname = NULL;
|
||||
const char *fp = NULL;
|
||||
int ret;
|
||||
|
||||
atname = synthetic_smb_fname(talloc_tos(),
|
||||
@ -1239,17 +1240,9 @@ const char *ReadDirName(struct smb_Dir *dir_hnd, char **ptalloced)
|
||||
TALLOC_FREE(talloced);
|
||||
continue;
|
||||
}
|
||||
fp = full_path_from_dirfsp_at_basename(atname,
|
||||
dir_hnd->fsp,
|
||||
n);
|
||||
if (fp == NULL) {
|
||||
TALLOC_FREE(atname);
|
||||
TALLOC_FREE(talloced);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (unlink_flags == INT_MAX) {
|
||||
DBG_NOTICE("ignoring %s\n", fp);
|
||||
DBG_NOTICE("ignoring %s/%s\n", dirname, n);
|
||||
TALLOC_FREE(atname);
|
||||
TALLOC_FREE(talloced);
|
||||
continue;
|
||||
@ -1259,18 +1252,23 @@ const char *ReadDirName(struct smb_Dir *dir_hnd, char **ptalloced)
|
||||
* We remove the stale tmpname
|
||||
* as root and ignore any errors
|
||||
*/
|
||||
DBG_NOTICE("unlink stale %s\n", fp);
|
||||
DBG_NOTICE("unlink stale %s/%s\n", dirname, n);
|
||||
become_root();
|
||||
ret = SMB_VFS_UNLINKAT(conn,
|
||||
dir_hnd->fsp,
|
||||
dirfsp,
|
||||
atname,
|
||||
unlink_flags);
|
||||
unbecome_root();
|
||||
if (ret == 0) {
|
||||
DBG_NOTICE("unlinked stale %s\n", fp);
|
||||
DBG_NOTICE("unlinked stale %s/%s\n",
|
||||
dirname,
|
||||
n);
|
||||
} else {
|
||||
DBG_WARNING("failed to unlink stale %s: %s\n",
|
||||
fp, strerror(errno));
|
||||
DBG_WARNING(
|
||||
"failed to unlink stale %s/%s: %s\n",
|
||||
dirname,
|
||||
n,
|
||||
strerror(errno));
|
||||
}
|
||||
TALLOC_FREE(atname);
|
||||
TALLOC_FREE(talloced);
|
||||
@ -1541,137 +1539,96 @@ bool opens_below_forall(struct connection_struct *conn,
|
||||
Is this directory empty ?
|
||||
*****************************************************************/
|
||||
|
||||
NTSTATUS can_delete_directory_fsp(files_struct *fsp)
|
||||
NTSTATUS can_delete_directory_hnd(struct smb_Dir *dir_hnd)
|
||||
{
|
||||
NTSTATUS status = NT_STATUS_OK;
|
||||
const char *dname = NULL;
|
||||
char *talloced = NULL;
|
||||
struct connection_struct *conn = fsp->conn;
|
||||
struct smb_Dir *dir_hnd = NULL;
|
||||
|
||||
status = OpenDir_from_pathref(talloc_tos(), fsp, NULL, 0, &dir_hnd);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
struct files_struct *dirfsp = dir_hnd_fetch_fsp(dir_hnd);
|
||||
struct connection_struct *conn = dirfsp->conn;
|
||||
bool delete_veto = lp_delete_veto_files(SNUM(conn));
|
||||
|
||||
while ((dname = ReadDirName(dir_hnd, &talloced))) {
|
||||
struct smb_filename *smb_dname_full = NULL;
|
||||
struct smb_filename *direntry_fname = NULL;
|
||||
char *fullname = NULL;
|
||||
int ret;
|
||||
|
||||
if (ISDOT(dname) || (ISDOTDOT(dname))) {
|
||||
TALLOC_FREE(talloced);
|
||||
continue;
|
||||
}
|
||||
if (IS_VETO_PATH(conn, dname)) {
|
||||
if (delete_veto && IS_VETO_PATH(conn, dname)) {
|
||||
TALLOC_FREE(talloced);
|
||||
continue;
|
||||
}
|
||||
|
||||
fullname = talloc_asprintf(talloc_tos(),
|
||||
"%s/%s",
|
||||
fsp->fsp_name->base_name,
|
||||
dname);
|
||||
if (fullname == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
direntry_fname = synthetic_smb_fname(talloc_tos(),
|
||||
dname,
|
||||
NULL,
|
||||
NULL,
|
||||
dirfsp->fsp_name->twrp,
|
||||
dirfsp->fsp_name->flags);
|
||||
TALLOC_FREE(talloced);
|
||||
dname = NULL;
|
||||
|
||||
smb_dname_full = synthetic_smb_fname(talloc_tos(),
|
||||
fullname,
|
||||
NULL,
|
||||
NULL,
|
||||
fsp->fsp_name->twrp,
|
||||
fsp->fsp_name->flags);
|
||||
if (smb_dname_full == NULL) {
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
if (direntry_fname == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = SMB_VFS_LSTAT(conn, smb_dname_full);
|
||||
if (ret != 0) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
break;
|
||||
}
|
||||
status = openat_pathref_fsp_lcomp(
|
||||
dirfsp,
|
||||
direntry_fname,
|
||||
UCF_POSIX_PATHNAMES /* no ci fallback */);
|
||||
|
||||
if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
|
||||
/* Could it be an msdfs link ? */
|
||||
if (lp_host_msdfs() &&
|
||||
lp_msdfs_root(SNUM(conn))) {
|
||||
struct smb_filename *smb_dname;
|
||||
smb_dname = synthetic_smb_fname(talloc_tos(),
|
||||
dname,
|
||||
NULL,
|
||||
&smb_dname_full->st,
|
||||
fsp->fsp_name->twrp,
|
||||
fsp->fsp_name->flags);
|
||||
if (smb_dname == NULL) {
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
if (is_msdfs_link(fsp, smb_dname)) {
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
TALLOC_FREE(smb_dname);
|
||||
DBG_DEBUG("got msdfs link name %s "
|
||||
"- can't delete directory %s\n",
|
||||
dname,
|
||||
fsp_str_dbg(fsp));
|
||||
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||
break;
|
||||
}
|
||||
TALLOC_FREE(smb_dname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DBG_DEBUG("Could not open %s: %s\n",
|
||||
direntry_fname->base_name,
|
||||
nt_errstr(status));
|
||||
|
||||
TALLOC_FREE(direntry_fname);
|
||||
|
||||
if (NT_STATUS_EQUAL(status,
|
||||
NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
|
||||
/* race between readdir and unlink */
|
||||
continue;
|
||||
}
|
||||
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||
break;
|
||||
}
|
||||
|
||||
if (S_ISLNK(direntry_fname->st.st_ex_mode)) {
|
||||
int ret;
|
||||
|
||||
if (lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) &&
|
||||
is_msdfs_link(dirfsp, direntry_fname))
|
||||
{
|
||||
|
||||
DBG_DEBUG("got msdfs link name %s "
|
||||
"- can't delete directory %s\n",
|
||||
direntry_fname->base_name,
|
||||
fsp_str_dbg(dirfsp));
|
||||
|
||||
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||
|
||||
TALLOC_FREE(direntry_fname);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Not a DFS link - could it be a dangling symlink ? */
|
||||
ret = SMB_VFS_STAT(conn, smb_dname_full);
|
||||
ret = SMB_VFS_FSTATAT(conn,
|
||||
dirfsp,
|
||||
direntry_fname,
|
||||
&direntry_fname->st,
|
||||
0 /* 0 means follow symlink */);
|
||||
if (ret == -1 && (errno == ENOENT || errno == ELOOP)) {
|
||||
/*
|
||||
* Dangling symlink.
|
||||
* Allow if "delete veto files = yes"
|
||||
*/
|
||||
if (lp_delete_veto_files(SNUM(conn))) {
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
TALLOC_FREE(direntry_fname);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
DBG_DEBUG("got symlink name %s - "
|
||||
"can't delete directory %s\n",
|
||||
dname,
|
||||
fsp_str_dbg(fsp));
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Not a symlink, get a pathref. */
|
||||
status = synthetic_pathref(talloc_tos(),
|
||||
fsp,
|
||||
dname,
|
||||
NULL,
|
||||
&smb_dname_full->st,
|
||||
fsp->fsp_name->twrp,
|
||||
fsp->fsp_name->flags,
|
||||
&direntry_fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!is_visible_fsp(direntry_fname->fsp)) {
|
||||
@ -1680,33 +1637,40 @@ NTSTATUS can_delete_directory_fsp(files_struct *fsp)
|
||||
* Allow if "delete veto files = yes"
|
||||
*/
|
||||
if (lp_delete_veto_files(SNUM(conn))) {
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
TALLOC_FREE(direntry_fname);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
DBG_DEBUG("got name %s - can't delete\n",
|
||||
direntry_fname->base_name);
|
||||
TALLOC_FREE(direntry_fname);
|
||||
|
||||
DBG_DEBUG("got name %s - can't delete\n", dname);
|
||||
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||
break;
|
||||
}
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(dir_hnd);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (have_file_open_below(fsp)) {
|
||||
if (have_file_open_below(dirfsp)) {
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
NTSTATUS can_delete_directory_fsp(files_struct *fsp)
|
||||
{
|
||||
struct smb_Dir *dir_hnd = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
status = OpenDir_from_pathref(talloc_tos(), fsp, NULL, 0, &dir_hnd);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
status = can_delete_directory_hnd(dir_hnd);
|
||||
TALLOC_FREE(dir_hnd);
|
||||
return status;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
struct smb_Dir;
|
||||
struct dptr_struct;
|
||||
|
||||
NTSTATUS can_delete_directory_hnd(struct smb_Dir *dir_hnd);
|
||||
NTSTATUS can_delete_directory_fsp(files_struct *fsp);
|
||||
struct files_struct *dir_hnd_fetch_fsp(struct smb_Dir *dir_hnd);
|
||||
uint16_t dptr_attr(struct smbd_server_connection *sconn, int key);
|
||||
|
@ -4749,7 +4749,7 @@ mkdir_first:
|
||||
&rhow);
|
||||
if (ret == -1 && errno == EINVAL) {
|
||||
/*
|
||||
* This is the strategie we use without having
|
||||
* This is the strategy we use without having
|
||||
* renameat2(RENAME_NOREPLACE):
|
||||
*
|
||||
* renameat() is able to replace a directory if the source is
|
||||
@ -5423,6 +5423,7 @@ void msg_file_was_renamed(struct messaging_context *msg_ctx,
|
||||
*/
|
||||
|
||||
static NTSTATUS open_streams_for_delete(connection_struct *conn,
|
||||
struct files_struct *dirfsp,
|
||||
const struct smb_filename *smb_fname)
|
||||
{
|
||||
struct stream_struct *stream_info = NULL;
|
||||
@ -5475,8 +5476,7 @@ static NTSTATUS open_streams_for_delete(connection_struct *conn,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
DEBUG(10, ("open_streams_for_delete found %d streams\n",
|
||||
num_streams));
|
||||
DBG_DEBUG("open_streams_for_delete found %u streams\n", num_streams);
|
||||
|
||||
if (num_streams == 0) {
|
||||
TALLOC_FREE(frame);
|
||||
@ -5522,7 +5522,7 @@ static NTSTATUS open_streams_for_delete(connection_struct *conn,
|
||||
status = SMB_VFS_CREATE_FILE(
|
||||
conn, /* conn */
|
||||
NULL, /* req */
|
||||
NULL, /* dirfsp */
|
||||
dirfsp, /* dirfsp */
|
||||
smb_fname_cp, /* fname */
|
||||
DELETE_ACCESS, /* access_mask */
|
||||
(FILE_SHARE_READ | /* share_access */
|
||||
@ -6222,7 +6222,7 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
|
||||
* We can't open a file with DELETE access if any of the
|
||||
* streams is open without FILE_SHARE_DELETE
|
||||
*/
|
||||
status = open_streams_for_delete(conn, smb_fname);
|
||||
status = open_streams_for_delete(conn, dirfsp, smb_fname);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto fail;
|
||||
|
@ -2181,22 +2181,18 @@ static NTSTATUS smb_q_unix_info2(
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
#if defined(HAVE_POSIX_ACLS)
|
||||
/****************************************************************************
|
||||
Utility function to open a fsp for a POSIX handle operation.
|
||||
****************************************************************************/
|
||||
|
||||
static NTSTATUS get_posix_fsp(connection_struct *conn,
|
||||
struct smb_request *req,
|
||||
struct files_struct *dirfsp,
|
||||
struct smb_filename *smb_fname,
|
||||
uint32_t access_mask,
|
||||
files_struct **ret_fsp)
|
||||
{
|
||||
NTSTATUS status;
|
||||
uint32_t create_disposition = FILE_OPEN;
|
||||
uint32_t share_access = FILE_SHARE_READ|
|
||||
FILE_SHARE_WRITE|
|
||||
FILE_SHARE_DELETE;
|
||||
struct smb2_create_blobs *posx = NULL;
|
||||
|
||||
/*
|
||||
@ -2204,7 +2200,6 @@ static NTSTATUS get_posix_fsp(connection_struct *conn,
|
||||
* but set reasonable defaults.
|
||||
*/
|
||||
uint32_t file_attributes = 0664;
|
||||
uint32_t oplock = NO_OPLOCK;
|
||||
uint32_t create_options = FILE_NON_DIRECTORY_FILE;
|
||||
|
||||
/* File or directory must exist. */
|
||||
@ -2234,31 +2229,34 @@ static NTSTATUS get_posix_fsp(connection_struct *conn,
|
||||
}
|
||||
|
||||
status = SMB_VFS_CREATE_FILE(
|
||||
conn, /* conn */
|
||||
req, /* req */
|
||||
NULL, /* dirfsp */
|
||||
smb_fname, /* fname */
|
||||
access_mask, /* access_mask */
|
||||
share_access, /* share_access */
|
||||
create_disposition,/* create_disposition*/
|
||||
create_options, /* create_options */
|
||||
file_attributes,/* file_attributes */
|
||||
oplock, /* oplock_request */
|
||||
NULL, /* lease */
|
||||
0, /* allocation_size */
|
||||
0, /* private_flags */
|
||||
NULL, /* sd */
|
||||
NULL, /* ea_list */
|
||||
ret_fsp, /* result */
|
||||
NULL, /* pinfo */
|
||||
posx, /* in_context */
|
||||
NULL); /* out_context */
|
||||
conn, /* conn */
|
||||
req, /* req */
|
||||
dirfsp, /* dirfsp */
|
||||
smb_fname, /* fname */
|
||||
access_mask, /* access_mask */
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE |
|
||||
FILE_SHARE_DELETE, /* share_access */
|
||||
FILE_OPEN, /* create_disposition*/
|
||||
create_options, /* create_options */
|
||||
file_attributes, /* file_attributes */
|
||||
NO_OPLOCK, /* oplock_request */
|
||||
NULL, /* lease */
|
||||
0, /* allocation_size */
|
||||
0, /* private_flags */
|
||||
NULL, /* sd */
|
||||
NULL, /* ea_list */
|
||||
ret_fsp, /* result */
|
||||
NULL, /* pinfo */
|
||||
posx, /* in_context */
|
||||
NULL); /* out_context */
|
||||
|
||||
done:
|
||||
TALLOC_FREE(posx);
|
||||
return status;
|
||||
}
|
||||
|
||||
#if defined(HAVE_POSIX_ACLS)
|
||||
|
||||
/****************************************************************************
|
||||
Utility function to count the number of entries in a POSIX acl.
|
||||
****************************************************************************/
|
||||
@ -2388,30 +2386,6 @@ static NTSTATUS smb_q_posix_acl(
|
||||
unsigned int size_needed = 0;
|
||||
NTSTATUS status;
|
||||
bool ok, refuse;
|
||||
bool close_fsp = false;
|
||||
|
||||
/*
|
||||
* Ensure we always operate on a file descriptor, not just
|
||||
* the filename.
|
||||
*/
|
||||
if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
|
||||
uint32_t access_mask = SEC_STD_READ_CONTROL|
|
||||
FILE_READ_ATTRIBUTES|
|
||||
FILE_WRITE_ATTRIBUTES;
|
||||
|
||||
status = get_posix_fsp(conn,
|
||||
req,
|
||||
smb_fname,
|
||||
access_mask,
|
||||
&fsp);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto out;
|
||||
}
|
||||
close_fsp = true;
|
||||
}
|
||||
|
||||
SMB_ASSERT(fsp != NULL);
|
||||
|
||||
refuse = refuse_symlink_fsp(fsp);
|
||||
if (refuse) {
|
||||
@ -2509,16 +2483,6 @@ static NTSTATUS smb_q_posix_acl(
|
||||
status = NT_STATUS_OK;
|
||||
|
||||
out:
|
||||
|
||||
if (close_fsp) {
|
||||
/*
|
||||
* Ensure the stat struct in smb_fname is up to
|
||||
* date. Structure copy.
|
||||
*/
|
||||
smb_fname->st = fsp->fsp_name->st;
|
||||
(void)close_file_free(req, &fsp, NORMAL_CLOSE);
|
||||
}
|
||||
|
||||
TALLOC_FREE(file_acl);
|
||||
TALLOC_FREE(def_acl);
|
||||
return status;
|
||||
@ -2762,15 +2726,25 @@ static void call_trans2qpathinfo(
|
||||
&total_data);
|
||||
break;
|
||||
|
||||
case SMB_QUERY_POSIX_ACL:
|
||||
case SMB_QUERY_POSIX_ACL: {
|
||||
struct files_struct *posix_fsp = NULL;
|
||||
|
||||
status = get_posix_fsp(conn,
|
||||
req,
|
||||
dirfsp,
|
||||
smb_fname,
|
||||
SEC_STD_READ_CONTROL |
|
||||
FILE_READ_ATTRIBUTES |
|
||||
FILE_WRITE_ATTRIBUTES,
|
||||
&posix_fsp);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
break;
|
||||
}
|
||||
status = smb_q_posix_acl(
|
||||
conn,
|
||||
req,
|
||||
smb_fname,
|
||||
smb_fname->fsp,
|
||||
ppdata,
|
||||
&total_data);
|
||||
conn, req, smb_fname, posix_fsp, ppdata, &total_data);
|
||||
(void)close_file_free(req, &posix_fsp, NORMAL_CLOSE);
|
||||
break;
|
||||
}
|
||||
|
||||
case SMB_QUERY_FILE_UNIX_LINK:
|
||||
status = smb_q_posix_symlink(conn,
|
||||
@ -3146,6 +3120,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
|
||||
struct smb_request *req,
|
||||
char **ppdata,
|
||||
int total_data,
|
||||
struct files_struct *dirfsp,
|
||||
struct smb_filename *smb_fname,
|
||||
int *pdata_return_size)
|
||||
{
|
||||
@ -3187,7 +3162,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
|
||||
status = SMB_VFS_CREATE_FILE(
|
||||
conn, /* conn */
|
||||
req, /* req */
|
||||
NULL, /* dirfsp */
|
||||
dirfsp, /* dirfsp */
|
||||
smb_fname, /* fname */
|
||||
FILE_READ_ATTRIBUTES, /* access_mask */
|
||||
FILE_SHARE_NONE, /* share_access */
|
||||
@ -3300,11 +3275,13 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
|
||||
wire_open_mode = IVAL(pdata,4);
|
||||
|
||||
if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
|
||||
return smb_posix_mkdir(conn, req,
|
||||
ppdata,
|
||||
total_data,
|
||||
smb_fname,
|
||||
pdata_return_size);
|
||||
return smb_posix_mkdir(conn,
|
||||
req,
|
||||
ppdata,
|
||||
total_data,
|
||||
dirfsp,
|
||||
smb_fname,
|
||||
pdata_return_size);
|
||||
}
|
||||
|
||||
switch (wire_open_mode & SMB_ACCMODE) {
|
||||
@ -3431,10 +3408,10 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
|
||||
create_options |= FILE_DIRECTORY_FILE;
|
||||
}
|
||||
|
||||
DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
(unsigned int)wire_open_mode,
|
||||
(unsigned int)unixmode ));
|
||||
DBG_DEBUG("file %s, smb_posix_flags = %" PRIu32 ", mode 0%o\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
wire_open_mode,
|
||||
(unsigned int)unixmode);
|
||||
|
||||
status = SMB_VFS_CREATE_FILE(
|
||||
conn, /* conn */
|
||||
@ -3994,9 +3971,9 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
|
||||
}
|
||||
|
||||
DBG_DEBUG("SMB_SET_FILE_UNIX_BASIC: name = "
|
||||
"%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
|
||||
"%s size = %jd, uid = %u, gid = %u, raw perms = 0%o\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
(double)size,
|
||||
(intmax_t)size,
|
||||
(unsigned int)set_owner,
|
||||
(unsigned int)set_grp,
|
||||
(int)raw_unixmode);
|
||||
@ -4044,10 +4021,10 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
|
||||
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
|
||||
DBG_DEBUG("SMB_SET_FILE_UNIX_BASIC "
|
||||
"setting mode 0%o for file %s\n",
|
||||
(unsigned int)unixmode,
|
||||
smb_fname_str_dbg(smb_fname)));
|
||||
smb_fname_str_dbg(smb_fname));
|
||||
ret = SMB_VFS_FCHMOD(fsp, unixmode);
|
||||
if (ret != 0) {
|
||||
return map_nt_error_from_unix(errno);
|
||||
@ -4267,7 +4244,6 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
|
||||
NTSTATUS status;
|
||||
unsigned int size_needed;
|
||||
unsigned int total_data;
|
||||
bool close_fsp = false;
|
||||
bool refuse;
|
||||
|
||||
if (total_data_in < 0) {
|
||||
@ -4329,32 +4305,6 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure we always operate on a file descriptor, not just
|
||||
* the filename.
|
||||
*/
|
||||
if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
|
||||
uint32_t access_mask = SEC_STD_WRITE_OWNER|
|
||||
SEC_STD_WRITE_DAC|
|
||||
SEC_STD_READ_CONTROL|
|
||||
FILE_READ_ATTRIBUTES|
|
||||
FILE_WRITE_ATTRIBUTES;
|
||||
|
||||
status = get_posix_fsp(conn,
|
||||
req,
|
||||
smb_fname,
|
||||
access_mask,
|
||||
&fsp);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto out;
|
||||
}
|
||||
close_fsp = true;
|
||||
}
|
||||
|
||||
/* Here we know fsp != NULL */
|
||||
SMB_ASSERT(fsp != NULL);
|
||||
|
||||
refuse = refuse_symlink_fsp(fsp);
|
||||
if (refuse) {
|
||||
status = NT_STATUS_ACCESS_DENIED;
|
||||
@ -4404,10 +4354,6 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
|
||||
status = NT_STATUS_OK;
|
||||
|
||||
out:
|
||||
|
||||
if (close_fsp) {
|
||||
(void)close_file_free(req, &fsp, NORMAL_CLOSE);
|
||||
}
|
||||
return status;
|
||||
#endif
|
||||
}
|
||||
@ -4568,21 +4514,34 @@ static void call_trans2setpathinfo(
|
||||
smb_fname->fsp,
|
||||
smb_fname);
|
||||
break;
|
||||
case SMB_SET_POSIX_ACL:
|
||||
case SMB_SET_POSIX_ACL: {
|
||||
struct files_struct *posix_fsp = NULL;
|
||||
|
||||
status = get_posix_fsp(conn,
|
||||
req,
|
||||
dirfsp,
|
||||
smb_fname,
|
||||
SEC_STD_WRITE_OWNER |
|
||||
SEC_STD_WRITE_DAC |
|
||||
SEC_STD_READ_CONTROL |
|
||||
FILE_READ_ATTRIBUTES |
|
||||
FILE_WRITE_ATTRIBUTES,
|
||||
&posix_fsp);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
break;
|
||||
}
|
||||
|
||||
status = smb_set_posix_acl(
|
||||
conn, req, *ppdata, total_data, NULL, smb_fname);
|
||||
conn, req, *ppdata, total_data, posix_fsp, smb_fname);
|
||||
(void)close_file_free(req, &posix_fsp, NORMAL_CLOSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (info_level_handled) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* smb_fname->fsp may be NULL if smb_fname points at a symlink
|
||||
* and we're in POSIX context, so be careful when using fsp
|
||||
* below, it can still be NULL.
|
||||
*/
|
||||
fsp = smb_fname->fsp;
|
||||
if (fsp == NULL) {
|
||||
status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
@ -4702,10 +4661,10 @@ static void call_trans2setfileinfo(
|
||||
*ppdata, 0,
|
||||
max_data_bytes);
|
||||
return;
|
||||
} else {
|
||||
reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
|
||||
return;
|
||||
} else {
|
||||
/*
|
||||
* Original code - this is an open file.
|
||||
|
@ -5052,11 +5052,10 @@ static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
size = IVAL(pdata,0);
|
||||
size |= (((off_t)IVAL(pdata,4)) << 32);
|
||||
DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
|
||||
"file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
|
||||
(double)size));
|
||||
size = (off_t)PULL_LE_U64(pdata, 0);
|
||||
DBG_DEBUG("Set end of file info for file %s to %ju\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
(uintmax_t)size);
|
||||
|
||||
return smb_set_file_size(conn, req,
|
||||
fsp,
|
||||
|
@ -342,8 +342,12 @@ static int DoWriteCommand( int argc, char **argv, bool debugflag, char *exename
|
||||
fixup_eventlog_record_tdb( &ee );
|
||||
|
||||
if ( opt_debug )
|
||||
printf( "record number [%d], tg [%d] , tw [%d]\n",
|
||||
ee.record_number, (int)ee.time_generated, (int)ee.time_written );
|
||||
printf("record number [%" PRIu32 "], "
|
||||
"tg [%" PRIu64 "] , "
|
||||
"tw [%" PRIu64 "]\n",
|
||||
ee.record_number,
|
||||
(uint64_t)ee.time_generated,
|
||||
(uint64_t)ee.time_written);
|
||||
|
||||
if ( ee.time_generated != 0 ) {
|
||||
|
||||
|
@ -355,8 +355,9 @@ static int account_set_minpwage(struct net_context *c,
|
||||
}
|
||||
|
||||
unix_to_nt_time_abs((NTTIME *)&i1->min_password_age, atoi(argv[0]));
|
||||
d_printf(_("Setting minimum password age to %d seconds\n"),
|
||||
(int)nt_time_to_unix_abs((NTTIME *)&i1->min_password_age));
|
||||
d_printf(_("Setting minimum password age to %" PRIu64 " seconds\n"),
|
||||
(uint64_t)nt_time_to_unix_abs(
|
||||
(NTTIME *)&i1->min_password_age));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
async seqnum
|
||||
Copyright (C) Volker Lendecke 2009
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "winbindd.h"
|
||||
#include "librpc/gen_ndr/ndr_winbind_c.h"
|
||||
|
||||
struct wb_seqnum_state {
|
||||
uint32_t seqnum;
|
||||
};
|
||||
|
||||
static void wb_seqnum_done(struct tevent_req *subreq);
|
||||
|
||||
struct tevent_req *wb_seqnum_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct winbindd_domain *domain)
|
||||
{
|
||||
struct tevent_req *req, *subreq;
|
||||
struct wb_seqnum_state *state;
|
||||
|
||||
req = tevent_req_create(mem_ctx, &state, struct wb_seqnum_state);
|
||||
if (req == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
subreq = dcerpc_wbint_QuerySequenceNumber_send(
|
||||
state, ev, dom_child_handle(domain), &state->seqnum);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
tevent_req_set_callback(subreq, wb_seqnum_done, req);
|
||||
return req;
|
||||
}
|
||||
|
||||
static void wb_seqnum_done(struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req = tevent_req_callback_data(
|
||||
subreq, struct tevent_req);
|
||||
struct wb_seqnum_state *state = tevent_req_data(
|
||||
req, struct wb_seqnum_state);
|
||||
NTSTATUS status, result;
|
||||
|
||||
status = dcerpc_wbint_QuerySequenceNumber_recv(subreq, state, &result);
|
||||
TALLOC_FREE(subreq);
|
||||
if (any_nt_status_not_ok(status, result, &status)) {
|
||||
tevent_req_nterror(req, status);
|
||||
return;
|
||||
}
|
||||
tevent_req_done(req);
|
||||
}
|
||||
|
||||
NTSTATUS wb_seqnum_recv(struct tevent_req *req, uint32_t *seqnum)
|
||||
{
|
||||
struct wb_seqnum_state *state = tevent_req_data(
|
||||
req, struct wb_seqnum_state);
|
||||
NTSTATUS status;
|
||||
|
||||
if (tevent_req_is_nterror(req, &status)) {
|
||||
return status;
|
||||
}
|
||||
*seqnum = state->seqnum;
|
||||
return NT_STATUS_OK;
|
||||
}
|
@ -1,153 +0,0 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
async seqnums, update the seqnums in winbindd_cache.c
|
||||
|
||||
Copyright (C) Volker Lendecke 2009
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "winbindd.h"
|
||||
#include "librpc/gen_ndr/ndr_winbind_c.h"
|
||||
|
||||
struct wb_seqnums_state {
|
||||
int num_domains;
|
||||
int num_received;
|
||||
|
||||
struct tevent_req **subreqs;
|
||||
struct winbindd_domain **domains;
|
||||
NTSTATUS *statuses;
|
||||
uint32_t *seqnums;
|
||||
};
|
||||
|
||||
static void wb_seqnums_done(struct tevent_req *subreq);
|
||||
|
||||
struct tevent_req *wb_seqnums_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev)
|
||||
{
|
||||
struct tevent_req *req;
|
||||
struct wb_seqnums_state *state;
|
||||
struct winbindd_domain *domain;
|
||||
int i;
|
||||
|
||||
req = tevent_req_create(mem_ctx, &state, struct wb_seqnums_state);
|
||||
if (req == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
state->num_received = 0;
|
||||
state->num_domains = 0;
|
||||
|
||||
for (domain = domain_list(); domain != NULL; domain = domain->next) {
|
||||
state->num_domains += 1;
|
||||
}
|
||||
|
||||
state->subreqs = talloc_array(state, struct tevent_req *,
|
||||
state->num_domains);
|
||||
state->domains = talloc_zero_array(state, struct winbindd_domain *,
|
||||
state->num_domains);
|
||||
state->statuses = talloc_array(state, NTSTATUS, state->num_domains);
|
||||
state->seqnums = talloc_array(state, uint32_t, state->num_domains);
|
||||
|
||||
if ((state->subreqs == NULL) || (state->domains == NULL) ||
|
||||
(state->statuses == NULL) || (state->seqnums == NULL)) {
|
||||
tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
for (domain = domain_list(); domain != NULL; domain = domain->next) {
|
||||
state->domains[i] = domain;
|
||||
state->subreqs[i] = wb_seqnum_send(state->subreqs, ev, domain);
|
||||
if (tevent_req_nomem(state->subreqs[i], req)) {
|
||||
/* Don't even start all the other requests */
|
||||
TALLOC_FREE(state->subreqs);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
tevent_req_set_callback(state->subreqs[i], wb_seqnums_done,
|
||||
req);
|
||||
i += 1;
|
||||
}
|
||||
return req;
|
||||
}
|
||||
|
||||
static void wb_seqnums_done(struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req = tevent_req_callback_data(
|
||||
subreq, struct tevent_req);
|
||||
struct wb_seqnums_state *state = tevent_req_data(
|
||||
req, struct wb_seqnums_state);
|
||||
NTSTATUS status;
|
||||
uint32_t seqnum;
|
||||
int i;
|
||||
|
||||
status = wb_seqnum_recv(subreq, &seqnum);
|
||||
|
||||
for (i=0; i<state->num_domains; i++) {
|
||||
if (subreq == state->subreqs[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < state->num_domains) {
|
||||
/* found one */
|
||||
|
||||
state->subreqs[i] = NULL;
|
||||
state->statuses[i] = status;
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
state->seqnums[i] = seqnum;
|
||||
|
||||
/*
|
||||
* This first assignment might be removed
|
||||
* later
|
||||
*/
|
||||
state->domains[i]->sequence_number = seqnum;
|
||||
|
||||
if (!wcache_store_seqnum(state->domains[i]->name,
|
||||
state->seqnums[i],
|
||||
time(NULL))) {
|
||||
DEBUG(1, ("wcache_store_seqnum failed for "
|
||||
"domain %s\n",
|
||||
state->domains[i]->name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TALLOC_FREE(subreq);
|
||||
|
||||
state->num_received += 1;
|
||||
|
||||
if (state->num_received >= state->num_domains) {
|
||||
tevent_req_done(req);
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS wb_seqnums_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
|
||||
int *num_domains, struct winbindd_domain ***domains,
|
||||
NTSTATUS **statuses, uint32_t **seqnums)
|
||||
{
|
||||
struct wb_seqnums_state *state = tevent_req_data(
|
||||
req, struct wb_seqnums_state);
|
||||
NTSTATUS status;
|
||||
|
||||
if (tevent_req_is_nterror(req, &status)) {
|
||||
return status;
|
||||
}
|
||||
*num_domains = state->num_domains;
|
||||
*domains = talloc_move(mem_ctx, &state->domains);
|
||||
*statuses = talloc_move(mem_ctx, &state->statuses);
|
||||
*seqnums = talloc_move(mem_ctx, &state->seqnums);
|
||||
return NT_STATUS_OK;
|
||||
}
|
@ -338,8 +338,6 @@ static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
|
||||
winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
|
||||
{ WINBINDD_GETGROUPS, "GETGROUPS",
|
||||
winbindd_getgroups_send, winbindd_getgroups_recv },
|
||||
{ WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
|
||||
winbindd_show_sequence_send, winbindd_show_sequence_recv },
|
||||
{ WINBINDD_GETGRGID, "GETGRGID",
|
||||
winbindd_getgrgid_send, winbindd_getgrgid_recv },
|
||||
{ WINBINDD_GETGRNAM, "GETGRNAM",
|
||||
|
@ -59,9 +59,11 @@ static void ads_cached_connection_reuse(ADS_STRUCT **adsp)
|
||||
|
||||
expire = nt_time_to_unix(ads->auth.expire_time);
|
||||
|
||||
DEBUG(7, ("Current tickets expire in %d seconds (at %d, time "
|
||||
"is now %d)\n", (uint32_t)expire - (uint32_t)now,
|
||||
(uint32_t) expire, (uint32_t) now));
|
||||
DBG_INFO("Current tickets expire in %" PRIu64 " seconds "
|
||||
"(at %" PRIu64 ", time is now %" PRIu64 ")\n",
|
||||
(uint64_t)expire - (uint64_t)now,
|
||||
(uint64_t)expire,
|
||||
(uint64_t)now);
|
||||
|
||||
if ( ads->config.realm && (expire > now)) {
|
||||
return;
|
||||
|
@ -502,8 +502,6 @@ NTSTATUS winbind_dual_SamLogon(struct winbindd_domain *domain,
|
||||
|
||||
struct winbindd_domain *domain_list(void);
|
||||
struct winbindd_domain *wb_next_domain(struct winbindd_domain *domain);
|
||||
bool set_routing_domain(struct winbindd_domain *domain,
|
||||
struct winbindd_domain *routing_domain);
|
||||
bool add_trusted_domain_from_auth(uint16_t validation_level,
|
||||
struct info3_text *info3,
|
||||
struct info6_text *info6);
|
||||
@ -742,24 +740,6 @@ struct tevent_req *winbindd_getgroups_send(TALLOC_CTX *mem_ctx,
|
||||
NTSTATUS winbindd_getgroups_recv(struct tevent_req *req,
|
||||
struct winbindd_response *response);
|
||||
|
||||
struct tevent_req *wb_seqnum_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct winbindd_domain *domain);
|
||||
NTSTATUS wb_seqnum_recv(struct tevent_req *req, uint32_t *seqnum);
|
||||
|
||||
struct tevent_req *wb_seqnums_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev);
|
||||
NTSTATUS wb_seqnums_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
|
||||
int *num_domains, struct winbindd_domain ***domains,
|
||||
NTSTATUS **statuses, uint32_t **seqnums);
|
||||
|
||||
struct tevent_req *winbindd_show_sequence_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct winbindd_cli_state *cli,
|
||||
struct winbindd_request *request);
|
||||
NTSTATUS winbindd_show_sequence_recv(struct tevent_req *req,
|
||||
struct winbindd_response *response);
|
||||
|
||||
struct tevent_req *wb_group_members_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
const struct dom_sid *sid,
|
||||
|
@ -1,167 +0,0 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
async implementation of WINBINDD_SHOW_SEQUENCE
|
||||
Copyright (C) Volker Lendecke 2009
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "winbindd.h"
|
||||
|
||||
struct winbindd_show_sequence_state {
|
||||
bool one_domain;
|
||||
/* One domain */
|
||||
uint32_t seqnum;
|
||||
|
||||
/* All domains */
|
||||
int num_domains;
|
||||
NTSTATUS *statuses;
|
||||
struct winbindd_domain **domains;
|
||||
uint32_t *seqnums;
|
||||
};
|
||||
|
||||
static void winbindd_show_sequence_done_one(struct tevent_req *subreq);
|
||||
static void winbindd_show_sequence_done_all(struct tevent_req *subreq);
|
||||
|
||||
struct tevent_req *winbindd_show_sequence_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct winbindd_cli_state *cli,
|
||||
struct winbindd_request *request)
|
||||
{
|
||||
struct tevent_req *req, *subreq;
|
||||
struct winbindd_show_sequence_state *state;
|
||||
|
||||
req = tevent_req_create(mem_ctx, &state,
|
||||
struct winbindd_show_sequence_state);
|
||||
if (req == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
state->one_domain = false;
|
||||
state->domains = NULL;
|
||||
state->statuses = NULL;
|
||||
state->seqnums = NULL;
|
||||
|
||||
/* Ensure null termination */
|
||||
request->domain_name[sizeof(request->domain_name)-1]='\0';
|
||||
|
||||
DEBUG(3, ("show_sequence %s\n", request->domain_name));
|
||||
|
||||
if (request->domain_name[0] != '\0') {
|
||||
struct winbindd_domain *domain;
|
||||
|
||||
state->one_domain = true;
|
||||
|
||||
domain = find_domain_from_name_noinit(
|
||||
request->domain_name);
|
||||
if (domain == NULL) {
|
||||
tevent_req_nterror(req, NT_STATUS_NO_SUCH_DOMAIN);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
subreq = wb_seqnum_send(state, ev, domain);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
tevent_req_set_callback(
|
||||
subreq, winbindd_show_sequence_done_one, req);
|
||||
return req;
|
||||
}
|
||||
|
||||
subreq = wb_seqnums_send(state, ev);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
tevent_req_set_callback(subreq, winbindd_show_sequence_done_all, req);
|
||||
return req;
|
||||
}
|
||||
|
||||
static void winbindd_show_sequence_done_one(struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req = tevent_req_callback_data(
|
||||
subreq, struct tevent_req);
|
||||
struct winbindd_show_sequence_state *state = tevent_req_data(
|
||||
req, struct winbindd_show_sequence_state);
|
||||
NTSTATUS status;
|
||||
|
||||
status = wb_seqnum_recv(subreq, &state->seqnum);
|
||||
TALLOC_FREE(subreq);
|
||||
if (tevent_req_nterror(req, status)) {
|
||||
return;
|
||||
}
|
||||
tevent_req_done(req);
|
||||
}
|
||||
|
||||
static void winbindd_show_sequence_done_all(struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req = tevent_req_callback_data(
|
||||
subreq, struct tevent_req);
|
||||
struct winbindd_show_sequence_state *state = tevent_req_data(
|
||||
req, struct winbindd_show_sequence_state);
|
||||
NTSTATUS status;
|
||||
|
||||
status = wb_seqnums_recv(subreq, state, &state->num_domains,
|
||||
&state->domains, &state->statuses,
|
||||
&state->seqnums);
|
||||
TALLOC_FREE(subreq);
|
||||
if (tevent_req_nterror(req, status)) {
|
||||
return;
|
||||
}
|
||||
tevent_req_done(req);
|
||||
}
|
||||
|
||||
NTSTATUS winbindd_show_sequence_recv(struct tevent_req *req,
|
||||
struct winbindd_response *response)
|
||||
{
|
||||
struct winbindd_show_sequence_state *state = tevent_req_data(
|
||||
req, struct winbindd_show_sequence_state);
|
||||
NTSTATUS status;
|
||||
char *extra_data;
|
||||
int i;
|
||||
|
||||
if (tevent_req_is_nterror(req, &status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (state->one_domain) {
|
||||
response->data.sequence_number = state->seqnum;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
extra_data = talloc_strdup(response, "");
|
||||
if (extra_data == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
for (i=0; i<state->num_domains; i++) {
|
||||
if (!NT_STATUS_IS_OK(state->statuses[i])
|
||||
|| (state->seqnums[i] == DOM_SEQUENCE_NONE)) {
|
||||
extra_data = talloc_asprintf_append_buffer(
|
||||
extra_data, "%s : DISCONNECTED\n",
|
||||
state->domains[i]->name);
|
||||
} else {
|
||||
extra_data = talloc_asprintf_append_buffer(
|
||||
extra_data, "%s : %d\n",
|
||||
state->domains[i]->name,
|
||||
(int)state->seqnums[i]);
|
||||
}
|
||||
if (extra_data == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
response->extra_data.data = extra_data;
|
||||
response->length += talloc_get_size(extra_data);
|
||||
return NT_STATUS_OK;
|
||||
}
|
@ -302,19 +302,6 @@ static NTSTATUS add_trusted_domain(const char *domain_name,
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
bool set_routing_domain(struct winbindd_domain *domain,
|
||||
struct winbindd_domain *routing_domain)
|
||||
{
|
||||
if (domain->routing_domain == NULL) {
|
||||
domain->routing_domain = routing_domain;
|
||||
return true;
|
||||
}
|
||||
if (domain->routing_domain != routing_domain) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool add_trusted_domain_from_auth(uint16_t validation_level,
|
||||
struct info3_text *info3,
|
||||
struct info6_text *info6)
|
||||
|
@ -208,8 +208,6 @@ bld.SAMBA3_SUBSYSTEM('winbindd-lib',
|
||||
wb_lookupusergroups.c
|
||||
wb_getpwsid.c
|
||||
wb_gettoken.c
|
||||
wb_seqnum.c
|
||||
wb_seqnums.c
|
||||
wb_group_members.c
|
||||
wb_alias_members.c
|
||||
wb_getgrsid.c
|
||||
@ -231,7 +229,6 @@ bld.SAMBA3_SUBSYSTEM('winbindd-lib',
|
||||
winbindd_getsidaliases.c
|
||||
winbindd_getuserdomgroups.c
|
||||
winbindd_getgroups.c
|
||||
winbindd_show_sequence.c
|
||||
winbindd_getgrgid.c
|
||||
winbindd_getgrnam.c
|
||||
winbindd_getusersids.c
|
||||
|
@ -736,162 +736,6 @@ static bool torture_winbind_struct_list_groups(struct torture_context *torture)
|
||||
return true;
|
||||
}
|
||||
|
||||
struct torture_domain_sequence {
|
||||
const char *netbios_name;
|
||||
uint32_t seq;
|
||||
};
|
||||
|
||||
static bool get_sequence_numbers(struct torture_context *torture,
|
||||
struct torture_domain_sequence **seqs)
|
||||
{
|
||||
struct winbindd_request req;
|
||||
struct winbindd_response rep;
|
||||
const char *extra_data;
|
||||
char line[256];
|
||||
uint32_t count = 0;
|
||||
struct torture_domain_sequence *s = NULL;
|
||||
|
||||
ZERO_STRUCT(req);
|
||||
ZERO_STRUCT(rep);
|
||||
|
||||
DO_STRUCT_REQ_REP(WINBINDD_SHOW_SEQUENCE, &req, &rep);
|
||||
|
||||
extra_data = (char *)rep.extra_data.data;
|
||||
torture_assert(torture, extra_data, "NULL sequence list");
|
||||
|
||||
while (next_token(&extra_data, line, "\n", sizeof(line))) {
|
||||
char *p, *lp;
|
||||
uint32_t seq;
|
||||
|
||||
s = talloc_realloc(torture, s, struct torture_domain_sequence,
|
||||
count + 2);
|
||||
ZERO_STRUCT(s[count+1]);
|
||||
|
||||
lp = line;
|
||||
p = strchr(lp, ' ');
|
||||
torture_assert(torture, p, "invalid line format");
|
||||
*p = 0;
|
||||
s[count].netbios_name = talloc_strdup(s, lp);
|
||||
|
||||
lp = p+1;
|
||||
torture_assert(torture, strncmp(lp, ": ", 2) == 0,
|
||||
"invalid line format");
|
||||
lp += 2;
|
||||
if (strcmp(lp, "DISCONNECTED") == 0) {
|
||||
seq = (uint32_t)-1;
|
||||
} else {
|
||||
seq = (uint32_t)strtol(lp, &p, 10);
|
||||
torture_assert(torture, (*p == '\0'),
|
||||
"invalid line format");
|
||||
torture_assert(torture, (seq != (uint32_t)-1),
|
||||
"sequence number -1 encountered");
|
||||
}
|
||||
s[count].seq = seq;
|
||||
|
||||
count++;
|
||||
}
|
||||
SAFE_FREE(rep.extra_data.data);
|
||||
|
||||
torture_assert(torture, count >= 2, "The list of domain sequence "
|
||||
"numbers should contain 2 entries");
|
||||
|
||||
*seqs = s;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool torture_winbind_struct_show_sequence(struct torture_context *torture)
|
||||
{
|
||||
bool ok;
|
||||
uint32_t i;
|
||||
struct torture_trust_domain *domlist = NULL;
|
||||
struct torture_domain_sequence *s = NULL;
|
||||
|
||||
torture_comment(torture, "Running WINBINDD_SHOW_SEQUENCE (struct based)\n");
|
||||
|
||||
ok = get_sequence_numbers(torture, &s);
|
||||
torture_assert(torture, ok, "failed to get list of sequence numbers");
|
||||
|
||||
ok = get_trusted_domains(torture, &domlist);
|
||||
torture_assert(torture, ok, "failed to get trust list");
|
||||
|
||||
for (i=0; domlist[i].netbios_name; i++) {
|
||||
struct winbindd_request req;
|
||||
struct winbindd_response rep;
|
||||
uint32_t seq;
|
||||
|
||||
torture_assert(torture, s[i].netbios_name,
|
||||
"more domains received in second run");
|
||||
torture_assert_str_equal(torture, domlist[i].netbios_name,
|
||||
s[i].netbios_name,
|
||||
"inconsistent order of domain lists");
|
||||
|
||||
ZERO_STRUCT(req);
|
||||
ZERO_STRUCT(rep);
|
||||
fstrcpy(req.domain_name, domlist[i].netbios_name);
|
||||
|
||||
ok = true;
|
||||
DO_STRUCT_REQ_REP_EXT(WINBINDD_SHOW_SEQUENCE, &req, &rep,
|
||||
NSS_STATUS_SUCCESS,
|
||||
false, ok = false,
|
||||
"WINBINDD_SHOW_SEQUENCE");
|
||||
if (ok == false) {
|
||||
torture_warning(torture,
|
||||
"WINBINDD_SHOW_SEQUENCE on "
|
||||
"domain %s failed\n",
|
||||
req.domain_name);
|
||||
|
||||
/*
|
||||
* Only fail for the first two domain that we
|
||||
* check specially below, otherwise we fail on
|
||||
* trusts generated by the LSA torture test
|
||||
* that do not really exist.
|
||||
*/
|
||||
if (i > 1) {
|
||||
/*
|
||||
* Do not confirm the sequence numbers
|
||||
* below
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
torture_comment(torture,
|
||||
"Full trust list for "
|
||||
"WINBINDD_SHOW_SEQUENCE "
|
||||
"test was:\n");
|
||||
for (i=0; domlist[i].netbios_name; i++) {
|
||||
torture_comment(torture,
|
||||
"%s\n",
|
||||
domlist[i].netbios_name);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
seq = rep.data.sequence_number;
|
||||
|
||||
if (i == 0) {
|
||||
torture_assert(torture, (seq != (uint32_t)-1),
|
||||
"BUILTIN domain disconnected");
|
||||
} else if (i == 1) {
|
||||
torture_assert(torture, (seq != (uint32_t)-1),
|
||||
"local domain disconnected");
|
||||
}
|
||||
|
||||
|
||||
if (seq == (uint32_t)-1) {
|
||||
torture_comment(torture, " * %s : DISCONNECTED\n",
|
||||
req.domain_name);
|
||||
} else {
|
||||
torture_comment(torture, " * %s : %d\n",
|
||||
req.domain_name, seq);
|
||||
}
|
||||
torture_assert(torture, (seq >= s[i].seq),
|
||||
"illegal sequence number encountered");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool torture_winbind_struct_setpwent(struct torture_context *torture)
|
||||
{
|
||||
struct winbindd_request req;
|
||||
@ -1174,7 +1018,6 @@ struct torture_suite *torture_winbind_struct_init(TALLOC_CTX *ctx)
|
||||
torture_suite_add_simple_test(suite, "dsgetdcname", torture_winbind_struct_dsgetdcname);
|
||||
torture_suite_add_simple_test(suite, "list_users", torture_winbind_struct_list_users);
|
||||
torture_suite_add_simple_test(suite, "list_groups", torture_winbind_struct_list_groups);
|
||||
torture_suite_add_simple_test(suite, "show_sequence", torture_winbind_struct_show_sequence);
|
||||
torture_suite_add_simple_test(suite, "setpwent", torture_winbind_struct_setpwent);
|
||||
torture_suite_add_simple_test(suite, "getpwent", torture_winbind_struct_getpwent);
|
||||
torture_suite_add_simple_test(suite, "endpwent", torture_winbind_struct_endpwent);
|
||||
|
Loading…
Reference in New Issue
Block a user