[SCM] Samba Shared Repository - branch master updated
Andrew Bartlett
abartlet at samba.org
Wed Jul 18 03:24:02 MDT 2012
The branch, master has been updated
via d0d05f8 s4-lib/tls: Try socket_send() multiple times to send partial packets
via 02a356e s4-librpc: Ensure we do not call call the decrpc timeout handler during gensec_update()
via fc36ebf s4-dbcheck: Check for and correct incorrect instanceType values
via e4001a7 dsdb: Allocate new OID to allow updates of a read-only replica
via 5630e25 s4-dsdb: Allow dbcheck to correct an incorrect instanceType
via 96db134 s4-dsdb: Ensure we never write read-only objects onto a read-write replica
from 127352c source4/torture: add talloc_stackframe()
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit d0d05f8474ed1882d373f042aba2c0209247678a
Author: Andrew Bartlett <abartlet at samba.org>
Date: Wed Jul 18 15:28:50 2012 +1000
s4-lib/tls: Try socket_send() multiple times to send partial packets
This works around an artificial limitation in socket_wrapper that breaks
some versions of GnuTLS when we return a short write.
Instead, keep pushing until the OS will not take it.
The correct solution will be to use tls_tstream, but the client code
for this is not yet tested and needs the ldap client layer changed
to use it.
Andrew Bartlett
Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
Autobuild-Date(master): Wed Jul 18 11:23:55 CEST 2012 on sn-devel-104
commit 02a356ea775a3ba589cb50af3c861ab86aaffa0b
Author: Andrew Bartlett <abartlet at samba.org>
Date: Mon Jul 9 14:37:28 2012 +1000
s4-librpc: Ensure we do not call call the decrpc timeout handler during gensec_update()
This avoids a situation where we could destroy pointers on the stack due to
a nested event loop.
This is certainly not a final, generic solution, but it is a minimal change
while we work to make gensec and gensec_gssapi async.
Andrew Bartlett
commit fc36ebfa7861cf7e86aa3c2110a6ab213424e8c1
Author: Andrew Bartlett <abartlet at samba.org>
Date: Tue Jul 17 11:10:41 2012 +1000
s4-dbcheck: Check for and correct incorrect instanceType values
commit e4001a78c1d0b286b37e19c733cf1bbc18166818
Author: Andrew Bartlett <abartlet at samba.org>
Date: Wed Jul 18 17:13:30 2012 +1000
dsdb: Allocate new OID to allow updates of a read-only replica
Normally this would be a very bad idea, but the specific case of fixing the instanceType
is the only case where this makes sense.
Andrew Bartlett
commit 5630e25a35ea95ca848281933a5a3a96306986a4
Author: Andrew Bartlett <abartlet at samba.org>
Date: Tue Jul 17 11:10:12 2012 +1000
s4-dsdb: Allow dbcheck to correct an incorrect instanceType
commit 96db13405bce8fa6d08b8b802439a606643e6db4
Author: Andrew Bartlett <abartlet at samba.org>
Date: Tue Jul 17 15:48:15 2012 +1000
s4-dsdb: Ensure we never write read-only objects onto a read-write replica
We should prevent this much further up the stack, but at least add a choke
at this point for now.
Additionally, this avoids administrator-forced replications causing
considerable damange to the directory.
Andrew Bartlett
-----------------------------------------------------------------------
Summary of changes:
source4/dsdb/pydsdb.c | 1 +
source4/dsdb/repl/replicated_objects.c | 9 ++++-
source4/dsdb/samdb/ldb_modules/instancetype.c | 8 ++-
source4/dsdb/samdb/ldb_modules/objectclass_attrs.c | 12 ++++--
source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 3 +-
source4/dsdb/samdb/samdb.h | 3 +
source4/lib/tls/tls.c | 39 +++++++++++------
source4/librpc/rpc/dcerpc.h | 8 ++++
source4/librpc/rpc/dcerpc_auth.c | 17 +++++++
source4/librpc/rpc/dcerpc_connect.c | 19 ++++++--
source4/scripting/python/samba/dbchecker.py | 45 ++++++++++++++++++++
source4/setup/schema_samba4.ldif | 1 +
12 files changed, 138 insertions(+), 27 deletions(-)
Changeset truncated at 500 lines:
diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c
index f63d71e..b9e1dd7 100644
--- a/source4/dsdb/pydsdb.c
+++ b/source4/dsdb/pydsdb.c
@@ -1269,6 +1269,7 @@ void initdsdb(void)
ADD_DSDB_STRING(DSDB_SYNTAX_STRING_DN);
ADD_DSDB_STRING(DSDB_SYNTAX_OR_NAME);
ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK);
+ ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA);
ADD_DSDB_STRING(DS_GUID_COMPUTERS_CONTAINER);
ADD_DSDB_STRING(DS_GUID_DELETED_OBJECTS_CONTAINER);
diff --git a/source4/dsdb/repl/replicated_objects.c b/source4/dsdb/repl/replicated_objects.c
index ec4dffe..67999df 100644
--- a/source4/dsdb/repl/replicated_objects.c
+++ b/source4/dsdb/repl/replicated_objects.c
@@ -202,6 +202,7 @@ WERROR dsdb_convert_object_ex(struct ldb_context *ldb,
uint32_t i;
struct ldb_message *msg;
struct replPropertyMetaDataBlob *md;
+ int instanceType;
struct ldb_val guid_value;
struct ldb_val parent_guid_value;
NTTIME whenChanged = 0;
@@ -352,12 +353,12 @@ WERROR dsdb_convert_object_ex(struct ldb_context *ldb,
}
+ instanceType = ldb_msg_find_attr_as_int(msg, "instanceType", 0);
if (dsdb_repl_flags & DSDB_REPL_FLAG_PARTIAL_REPLICA) {
/* the instanceType type for partial_replica
replication is sent via DRS with TYPE_WRITE set, but
must be used on the client with TYPE_WRITE removed
*/
- int instanceType = ldb_msg_find_attr_as_int(msg, "instanceType", 0);
if (instanceType & INSTANCE_TYPE_WRITE) {
instanceType &= ~INSTANCE_TYPE_WRITE;
ldb_msg_remove_attr(msg, "instanceType");
@@ -365,6 +366,12 @@ WERROR dsdb_convert_object_ex(struct ldb_context *ldb,
return WERR_INTERNAL_ERROR;
}
}
+ } else {
+ if (!(instanceType & INSTANCE_TYPE_WRITE)) {
+ DEBUG(0, ("Refusing to replicate %s from a read-only repilca into a read-write replica!\n",
+ ldb_dn_get_linearized(msg->dn)));
+ return WERR_DS_DRA_SOURCE_IS_PARTIAL_REPLICA;
+ }
}
whenChanged_t = nt_time_to_unix(whenChanged);
diff --git a/source4/dsdb/samdb/ldb_modules/instancetype.c b/source4/dsdb/samdb/ldb_modules/instancetype.c
index d743d4f..7bf95f3 100644
--- a/source4/dsdb/samdb/ldb_modules/instancetype.c
+++ b/source4/dsdb/samdb/ldb_modules/instancetype.c
@@ -136,10 +136,12 @@ static int instancetype_mod(struct ldb_module *module, struct ldb_request *req)
el = ldb_msg_find_element(req->op.mod.message, "instanceType");
if (el != NULL) {
- ldb_set_errstring(ldb, "instancetype: the 'instanceType' attribute can never be changed!");
- return LDB_ERR_CONSTRAINT_VIOLATION;
+ /* Except to allow dbcheck to fix things, this must never be modified */
+ if (!ldb_request_get_control(req, DSDB_CONTROL_DBCHECK)) {
+ ldb_set_errstring(ldb, "instancetype: the 'instanceType' attribute can never be changed!");
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
}
-
return ldb_next_request(module, req);
}
diff --git a/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c b/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c
index e50c8e2..c521f33 100644
--- a/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c
+++ b/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c
@@ -408,10 +408,14 @@ static int attr_handler2(struct oc_context *ac)
found = str_list_check(harmless_attrs, attr->lDAPDisplayName);
}
if (!found) {
- ldb_asprintf_errstring(ldb, "objectclass_attrs: attribute '%s' on entry '%s' does not exist in the specified objectclasses!",
- msg->elements[i].name,
- ldb_dn_get_linearized(msg->dn));
- return LDB_ERR_OBJECT_CLASS_VIOLATION;
+ /* we allow this for dbcheck to fix the rest of this broken entry */
+ if (!ldb_request_get_control(ac->req, DSDB_CONTROL_DBCHECK) ||
+ ac->req->operation == LDB_ADD) {
+ ldb_asprintf_errstring(ldb, "objectclass_attrs: attribute '%s' on entry '%s' does not exist in the specified objectclasses!",
+ msg->elements[i].name,
+ ldb_dn_get_linearized(msg->dn));
+ return LDB_ERR_OBJECT_CLASS_VIOLATION;
+ }
}
}
diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
index 1dc7ea0..6f26299 100644
--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
+++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
@@ -1391,7 +1391,8 @@ static int replmd_update_rpmd(struct ldb_module *module,
struct ldb_message_element *el;
/*if we are RODC and this is a DRSR update then its ok*/
- if (!ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
+ if (!ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)
+ && !ldb_request_get_control(req, DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA)) {
unsigned instanceType;
ret = samdb_rodc(ldb, rodc);
diff --git a/source4/dsdb/samdb/samdb.h b/source4/dsdb/samdb/samdb.h
index 5422218..c4cb3bd 100644
--- a/source4/dsdb/samdb/samdb.h
+++ b/source4/dsdb/samdb/samdb.h
@@ -122,6 +122,9 @@ struct dsdb_control_password_change {
/* passed when we want special behaviour for dbcheck */
#define DSDB_CONTROL_DBCHECK "1.3.6.1.4.1.7165.4.3.19"
+/* passed when dbcheck wants to modify a read only replica (very special case) */
+#define DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA "1.3.6.1.4.1.7165.4.3.19.1"
+
/* passed when importing plain text password on upgrades */
#define DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID "1.3.6.1.4.1.7165.4.3.20"
diff --git a/source4/lib/tls/tls.c b/source4/lib/tls/tls.c
index 7bf2ff8..db6d1eb 100644
--- a/source4/lib/tls/tls.c
+++ b/source4/lib/tls/tls.c
@@ -152,7 +152,7 @@ static ssize_t tls_push(gnutls_transport_ptr ptr, const void *buf, size_t size)
{
struct tls_context *tls = talloc_get_type(ptr, struct tls_context);
NTSTATUS status;
- size_t nwritten;
+ size_t nwritten, total_nwritten = 0;
DATA_BLOB b;
if (!tls->tls_enabled) {
@@ -162,19 +162,32 @@ static ssize_t tls_push(gnutls_transport_ptr ptr, const void *buf, size_t size)
b.data = discard_const(buf);
b.length = size;
- status = socket_send(tls->socket, &b, &nwritten);
- if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
- errno = EAGAIN;
- return -1;
- }
- if (!NT_STATUS_IS_OK(status)) {
- TEVENT_FD_WRITEABLE(tls->fde);
- return -1;
- }
- if (size != nwritten) {
+ /* Cope with socket_wrapper 1500 byte chunking for PCAP */
+ do {
+ status = socket_send(tls->socket, &b, &nwritten);
+
+ if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
+ errno = EAGAIN;
+ return -1;
+ }
+ if (!NT_STATUS_IS_OK(status)) {
+ TEVENT_FD_WRITEABLE(tls->fde);
+ return -1;
+ }
+
+ total_nwritten += nwritten;
+
+ if (size == nwritten) {
+ break;
+ }
+
+ b.data += nwritten;
+ b.length -= nwritten;
+
TEVENT_FD_WRITEABLE(tls->fde);
- }
- return nwritten;
+ } while (b.length);
+
+ return total_nwritten;
}
/*
diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h
index 359efda..ef83086 100644
--- a/source4/librpc/rpc/dcerpc.h
+++ b/source4/librpc/rpc/dcerpc.h
@@ -124,6 +124,14 @@ struct dcerpc_pipe {
/** timeout for individual rpc requests, in seconds */
uint32_t request_timeout;
+
+ /*
+ * Set for the timeout in dcerpc_pipe_connect_b_send(), to
+ * allow the timeout not to destory the stack during a nested
+ * event loop caused by gensec_update()
+ */
+ bool inhibit_timeout_processing;
+ bool timed_out;
};
/* default timeout for all rpc requests, in seconds */
diff --git a/source4/librpc/rpc/dcerpc_auth.c b/source4/librpc/rpc/dcerpc_auth.c
index cedcdd1..d5e5620 100644
--- a/source4/librpc/rpc/dcerpc_auth.c
+++ b/source4/librpc/rpc/dcerpc_auth.c
@@ -151,10 +151,19 @@ static void bind_auth_next_step(struct composite_context *c)
* it doesn't like that either
*/
+ state->pipe->inhibit_timeout_processing = true;
+ state->pipe->timed_out = false;
+
c->status = gensec_update(sec->generic_state, state,
state->pipe->conn->event_ctx,
sec->auth_info->credentials,
&state->credentials);
+ if (state->pipe->timed_out) {
+ composite_error(c, NT_STATUS_IO_TIMEOUT);
+ return;
+ }
+ state->pipe->inhibit_timeout_processing = false;
+
data_blob_free(&sec->auth_info->credentials);
if (NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
@@ -358,10 +367,18 @@ struct composite_context *dcerpc_bind_auth_send(TALLOC_CTX *mem_ctx,
* it doesn't like that either
*/
+ state->pipe->inhibit_timeout_processing = true;
+ state->pipe->timed_out = false;
c->status = gensec_update(sec->generic_state, state,
p->conn->event_ctx,
sec->auth_info->credentials,
&state->credentials);
+ if (state->pipe->timed_out) {
+ composite_error(c, NT_STATUS_IO_TIMEOUT);
+ return c;
+ }
+ state->pipe->inhibit_timeout_processing = false;
+
if (!NT_STATUS_IS_OK(c->status) &&
!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
composite_error(c, c->status);
diff --git a/source4/librpc/rpc/dcerpc_connect.c b/source4/librpc/rpc/dcerpc_connect.c
index 8cf60e6..821499e 100644
--- a/source4/librpc/rpc/dcerpc_connect.c
+++ b/source4/librpc/rpc/dcerpc_connect.c
@@ -716,8 +716,14 @@ static void continue_pipe_auth(struct composite_context *ctx)
static void dcerpc_connect_timeout_handler(struct tevent_context *ev, struct tevent_timer *te,
struct timeval t, void *private_data)
{
- struct composite_context *c = talloc_get_type(private_data, struct composite_context);
- composite_error(c, NT_STATUS_IO_TIMEOUT);
+ struct composite_context *c = talloc_get_type(private_data,
+ struct composite_context);
+ struct pipe_connect_state *s = talloc_get_type(c->private_data, struct pipe_connect_state);
+ if (!s->pipe->inhibit_timeout_processing) {
+ composite_error(c, NT_STATUS_IO_TIMEOUT);
+ } else {
+ s->pipe->timed_out = true;
+ }
}
/*
@@ -757,9 +763,12 @@ _PUBLIC_ struct composite_context* dcerpc_pipe_connect_b_send(TALLOC_CTX *parent
s->credentials = credentials;
s->lp_ctx = lp_ctx;
- tevent_add_timer(c->event_ctx, c,
- timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
- dcerpc_connect_timeout_handler, c);
+ s->pipe->timed_out = false;
+ s->pipe->inhibit_timeout_processing = false;
+
+ tevent_add_timer(c->event_ctx, s,
+ timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
+ dcerpc_connect_timeout_handler, s);
switch (s->binding->transport) {
case NCA_UNKNOWN: {
diff --git a/source4/scripting/python/samba/dbchecker.py b/source4/scripting/python/samba/dbchecker.py
index 284c529..03ec7ab 100644
--- a/source4/scripting/python/samba/dbchecker.py
+++ b/source4/scripting/python/samba/dbchecker.py
@@ -51,11 +51,19 @@ class dbcheck(object):
self.fix_rmd_flags = False
self.seize_fsmo_role = False
self.move_to_lost_and_found = False
+ self.fix_instancetype = False
self.in_transaction = in_transaction
self.infrastructure_dn = ldb.Dn(samdb, "CN=Infrastructure," + samdb.domain_dn())
self.naming_dn = ldb.Dn(samdb, "CN=Partitions,%s" % samdb.get_config_basedn())
self.schema_dn = samdb.get_schema_basedn()
self.rid_dn = ldb.Dn(samdb, "CN=RID Manager$,CN=System," + samdb.domain_dn())
+ self.ntds_dsa = samdb.get_dsServiceName()
+
+ res = self.samdb.search(base=self.ntds_dsa, scope=ldb.SCOPE_BASE, attrs=['msDS-hasMasterNCs'])
+ if "msDS-hasMasterNCs" in res[0]:
+ self.write_ncs = res[0]["msDS-hasMasterNCs"]
+ else:
+ self.write_ncs = None
def check_database(self, DN=None, scope=ldb.SCOPE_SUBTREE, controls=[], attrs=['*']):
'''perform a database check, returning the number of errors found'''
@@ -366,6 +374,20 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
"Failed to rename object %s into lostAndFound at %s" % (obj.dn, new_dn + lost_and_found)):
self.report("Renamed object %s into lostAndFound at %s" % (obj.dn, new_dn + lost_and_found))
+ def err_wrong_instancetype(self, obj, calculated_instancetype):
+ '''handle a wrong instanceType'''
+ self.report("ERROR: wrong instanceType %s on %s, should be %d" % (obj["instanceType"], obj.dn, calculated_instancetype))
+ if not self.confirm_all('Change instanceType from %s to %d on %s?' % (obj["instanceType"], calculated_instancetype, obj.dn), 'fix_instancetype'):
+ self.report('Not changing instanceType from %s to %d on %s' % (obj["instanceType"], calculated_instancetype, obj.dn))
+ return
+
+ m = ldb.Message()
+ m.dn = obj.dn
+ m['value'] = ldb.MessageElement(str(calculated_instancetype), ldb.FLAG_MOD_REPLACE, 'instanceType')
+ if self.do_modify(m, ["local_oid:%s:0" % dsdb.DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA],
+ "Failed to correct missing instanceType on %s by setting instanceType=%d" % (obj.dn, calculated_instancetype)):
+ self.report("Corrected instancetype on %s by setting instanceType=%d" % (obj.dn, calculated_instancetype))
+
def find_revealed_link(self, dn, attrname, guid):
'''return a revealed link in an object'''
res = self.samdb.search(base=dn, scope=ldb.SCOPE_BASE, attrs=[attrname],
@@ -511,6 +533,24 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
return False
+ def calculate_instancetype(self, dn):
+ instancetype = 0
+ nc_root = self.samdb.get_nc_root(dn)
+ if dn == nc_root:
+ instancetype |= dsdb.INSTANCE_TYPE_IS_NC_HEAD
+ try:
+ self.samdb.search(base=dn.parent(), scope=ldb.SCOPE_BASE, attrs=[], controls=["show_recycled:1"])
+ except ldb.LdbError, (enum, estr):
+ if enum != ldb.ERR_NO_SUCH_OBJECT:
+ raise
+ else:
+ instancetype |= dsdb.INSTANCE_TYPE_NC_ABOVE
+
+ if self.write_ncs is not None and str(nc_root) in self.write_ncs:
+ instancetype |= dsdb.INSTANCE_TYPE_WRITE
+
+ return instancetype
+
def check_object(self, dn, attrs=['*']):
'''check one object'''
if self.verbose:
@@ -589,6 +629,11 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
error_count += 1
break
+ if str(attrname).lower() == "instancetype":
+ calculated_instancetype = self.calculate_instancetype(dn)
+ if len(obj["instanceType"]) != 1 or obj["instanceType"][0] != str(calculated_instancetype):
+ self.err_wrong_instancetype(obj, calculated_instancetype)
+
show_dn = True
if got_repl_property_meta_data:
rdn = (str(dn).split(","))[0]
diff --git a/source4/setup/schema_samba4.ldif b/source4/setup/schema_samba4.ldif
index 3d004c5..0c5c787 100644
--- a/source4/setup/schema_samba4.ldif
+++ b/source4/setup/schema_samba4.ldif
@@ -194,6 +194,7 @@
#Allocated: DSDB_CONTROL_NO_GLOBAL_CATALOG 1.3.6.1.4.1.7165.4.3.17
#Allocated: DSDB_CONTROL_PARTIAL_REPLICA 1.3.6.1.4.1.7165.4.3.18
#Allocated: DSDB_CONTROL_DBCHECK 1.3.6.1.4.1.7165.4.3.19
+#Allocated: DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA 1.3.6.1.4.1.7165.4.3.19.1
#Allocated: DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID 1.3.6.1.4.1.7165.4.3.20
# Extended 1.3.6.1.4.1.7165.4.4.x
--
Samba Shared Repository
More information about the samba-cvs
mailing list