View | Details | Raw Unified | Return to bug 39806 | Differences between
and this patch

Collapse All | Expand All

(-)a/source4/dns_server/dlz_bind9.c (-4 / +48 lines)
 Lines 63-68   struct dlz_bind9_data { Link Here 
63
	struct smb_krb5_context *smb_krb5_ctx;
63
	struct smb_krb5_context *smb_krb5_ctx;
64
	struct auth4_context *auth_context;
64
	struct auth4_context *auth_context;
65
	struct auth_session_info *session_info;
65
	struct auth_session_info *session_info;
66
	bool is_system_session;
66
	char *update_name;
67
	char *update_name;
67
68
68
	/* helper functions from the dlz_dlopen driver */
69
	/* helper functions from the dlz_dlopen driver */
 Lines 736-741   _PUBLIC_ void dlz_destroy(void *dbdata) Link Here 
736
	dlz_bind9_state_ref_count--;
737
	dlz_bind9_state_ref_count--;
737
	if (dlz_bind9_state_ref_count == 0) {
738
	if (dlz_bind9_state_ref_count == 0) {
738
		talloc_unlink(state, state->samdb);
739
		talloc_unlink(state, state->samdb);
740
		if (state->is_system_session) {
741
			state->session_info = NULL;
742
		}
739
		talloc_free(state);
743
		talloc_free(state);
740
		dlz_bind9_state = NULL;
744
		dlz_bind9_state = NULL;
741
	}
745
	}
 Lines 1269-1274   static bool b9_is_tombstoned(struct ldb_result *res) { Link Here 
1269
}
1273
}
1270
1274
1271
/*
1275
/*
1276
 * If `name` is a computer account (ends in $) and the records's field matches
1277
 * the account name (without the $), the account owns the record.
1278
 */
1279
static bool b9_account_owns_record(const char *name, struct ldb_result *record) {
1280
	char *dc = NULL;
1281
	size_t len = strlen(name);
1282
1283
	struct ldb_message_element *el = ldb_msg_find_element(record->msgs[0], "dc");
1284
	if (el != NULL && el->num_values > 0) {
1285
		dc = (char *) el->values[0].data;
1286
	}
1287
1288
	if (dc != NULL && len > 0 && name[len - 1] == '$') {
1289
		return strncmp(name, dc, len - 1) == 0;
1290
	}
1291
	return false;
1292
}
1293
1294
/*
1272
  authorize a zone update
1295
  authorize a zone update
1273
 */
1296
 */
1274
_PUBLIC_ isc_boolean_t dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr,
1297
_PUBLIC_ isc_boolean_t dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr,
 Lines 1285-1300   _PUBLIC_ isc_boolean_t dlz_ssumatch(const char *signer, const char *name, const Link Here 
1285
	NTSTATUS nt_status;
1308
	NTSTATUS nt_status;
1286
	struct gensec_security *gensec_ctx;
1309
	struct gensec_security *gensec_ctx;
1287
	struct auth_session_info *session_info;
1310
	struct auth_session_info *session_info;
1311
	bool is_system_session = false;
1288
	struct ldb_dn *dn;
1312
	struct ldb_dn *dn;
1289
	isc_result_t result;
1313
	isc_result_t result;
1290
	struct ldb_result *res;
1314
	struct ldb_result *res;
1291
	const char * attrs[] = { "dNSTombstoned", NULL };
1315
	const char * attrs[] = { "dNSTombstoned", "dc", NULL };
1292
	uint32_t access_mask;
1316
	uint32_t access_mask;
1293
	bool is_tombstoned = false;
1317
	bool is_tombstoned = false;
1318
	bool owns_record = false;
1294
1319
1295
	/* Remove cached credentials, if any */
1320
	/* Remove cached credentials, if any */
1296
	if (state->session_info) {
1321
	if (state->session_info) {
1297
		talloc_free(state->session_info);
1322
		if (!state->is_system_session) {
1323
			talloc_free(state->session_info);
1324
		}
1325
		state->is_system_session = false;
1298
		state->session_info = NULL;
1326
		state->session_info = NULL;
1299
	}
1327
	}
1300
	if (state->update_name) {
1328
	if (state->update_name) {
 Lines 1381-1386   _PUBLIC_ isc_boolean_t dlz_ssumatch(const char *signer, const char *name, const Link Here 
1381
	} else if (ldb_ret == LDB_SUCCESS) {
1409
	} else if (ldb_ret == LDB_SUCCESS) {
1382
		access_mask = SEC_STD_REQUIRED | SEC_ADS_SELF_WRITE;
1410
		access_mask = SEC_STD_REQUIRED | SEC_ADS_SELF_WRITE;
1383
		is_tombstoned = b9_is_tombstoned(res);
1411
		is_tombstoned = b9_is_tombstoned(res);
1412
		owns_record = b9_account_owns_record(session_info->info->account_name, res);
1384
		talloc_free(res);
1413
		talloc_free(res);
1385
	} else {
1414
	} else {
1386
		talloc_free(tmp_ctx);
1415
		talloc_free(tmp_ctx);
 Lines 1412-1417   _PUBLIC_ isc_boolean_t dlz_ssumatch(const char *signer, const char *name, const Link Here 
1412
						  session_info->security_token,
1441
						  session_info->security_token,
1413
						  access_mask, NULL);
1442
						  access_mask, NULL);
1414
	}
1443
	}
1444
	/* Univention Specific: If a machine tries to access a forward/zone
1445
	 * without the proper access-rights, but the account of the requesting
1446
	 * machine matches the `dc` attribute of the record, a modification is
1447
	 * allowed and the privileges for this operation are escalated to
1448
	 * `SYSTEM`.
1449
	 */
1450
	if (ldb_ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS && owns_record) {
1451
		session_info = system_session(state->lp);
1452
		is_system_session = true;
1453
		ldb_ret = LDB_SUCCESS;
1454
	}
1415
	if (ldb_ret != LDB_SUCCESS) {
1455
	if (ldb_ret != LDB_SUCCESS) {
1416
		state->log(ISC_LOG_INFO,
1456
		state->log(ISC_LOG_INFO,
1417
			"samba_dlz: disallowing update of signer=%s name=%s type=%s error=%s",
1457
			"samba_dlz: disallowing update of signer=%s name=%s type=%s error=%s",
 Lines 1427-1433   _PUBLIC_ isc_boolean_t dlz_ssumatch(const char *signer, const char *name, const Link Here 
1427
		talloc_free(tmp_ctx);
1467
		talloc_free(tmp_ctx);
1428
		return ISC_FALSE;
1468
		return ISC_FALSE;
1429
	}
1469
	}
1430
	state->session_info = talloc_steal(state, session_info);
1470
	state->is_system_session = is_system_session;
1471
	if (is_system_session) {
1472
		state->session_info = session_info;
1473
	} else {
1474
		state->session_info = talloc_steal(state, session_info);
1475
	}
1431
1476
1432
	state->log(ISC_LOG_INFO, "samba_dlz: allowing update of signer=%s name=%s tcpaddr=%s type=%s key=%s",
1477
	state->log(ISC_LOG_INFO, "samba_dlz: allowing update of signer=%s name=%s tcpaddr=%s type=%s key=%s",
1433
		   signer, name, tcpaddr, type, key);
1478
		   signer, name, tcpaddr, type, key);
1434
- 

Return to bug 39806