Beispiel #1
0
static bool test_internal_dns_update_self(struct torture_context *tctx)
{
	struct dns_connection *conn;
	struct dns_update_request *req, *resp;
	struct dns_rrec *rec = NULL;
	char *host;
	DNS_ERROR err;
	struct sockaddr_storage *ss;

	conn = setup_connection(tctx);
	if (conn == NULL) {
		return false;
	}

	host = talloc_asprintf(tctx, "%s.%s", getenv("DC_SERVER"), get_dns_domain(tctx));
	if (host == NULL) {
		return false;
	}

	err = dns_create_update(conn, get_dns_domain(tctx), &req);
	if (!ERR_DNS_IS_OK(err)) {
		printf("Failed to update packet\n");
		return false;
	}

	ss = str_to_sockaddr(conn, getenv("DC_SERVER_IP"));
	if (ss == NULL) {
		printf("Converting '%s' to sockaddr_storage failed\n", getenv("DC_SERVER_IP"));
		return false;
	}

	err = dns_create_a_record(req, host, 300, ss, &rec);
	if (!ERR_DNS_IS_OK(err)) {
		printf("Failed to create A update record\n");
		return false;
	}

	err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
	if (!ERR_DNS_IS_OK(err)) {
		printf("Failed to add A update record to update packet\n");
		return false;
	}

	err = dns_update_transaction(conn, conn, req, &resp);
	if (!ERR_DNS_IS_OK(err)) {
		printf("Failed to send update\n");
		return false;
	}

	if (dns_response_code(resp->flags) != DNS_REFUSED) {
		printf("Update returned %u\n", dns_response_code(resp->flags));
		return false;
	}

	/* FIXME: is there _any_ way to unmarshal the response to check this? */

	return true;
}
Beispiel #2
0
static DNS_ERROR dns_negotiate_gss_ctx_int( TALLOC_CTX *mem_ctx,
					    struct dns_connection *conn,
					    const char *keyname,
					    const gss_name_t target_name,
					    gss_ctx_id_t *ctx, 
					    enum dns_ServerType srv_type )
{
	struct gss_buffer_desc_struct input_desc, *input_ptr, output_desc;
	OM_uint32 major, minor;
	OM_uint32 ret_flags;
	DNS_ERROR err;

	gss_OID_desc krb5_oid_desc =
		{ 9, (const char *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" };

	*ctx = GSS_C_NO_CONTEXT;
	input_ptr = NULL;

	do {
		major = gss_init_sec_context(
			&minor, NULL, ctx, target_name, &krb5_oid_desc,
			GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG |
			GSS_C_CONF_FLAG |
			GSS_C_INTEG_FLAG,
			0, NULL, input_ptr, NULL, &output_desc,
			&ret_flags, NULL );

		if (input_ptr != NULL) {
			TALLOC_FREE(input_desc.value);
		}

		if (output_desc.length != 0) {

			struct dns_request *req;
			struct dns_rrec *rec;
			struct dns_buffer *buf;

			time_t t = time(NULL);

			err = dns_create_query(mem_ctx, keyname, QTYPE_TKEY,
					       DNS_CLASS_IN, &req);
			if (!ERR_DNS_IS_OK(err)) goto error;

			err = dns_create_tkey_record(
				req, keyname, "gss.microsoft.com", t,
				t + 86400, DNS_TKEY_MODE_GSSAPI, 0,
				output_desc.length, (uint8 *)output_desc.value,
				&rec );
			if (!ERR_DNS_IS_OK(err)) goto error;

			/* Windows 2000 DNS is broken and requires the
			   TKEY payload in the Answer section instead
			   of the Additional seciton like Windows 2003 */

			if ( srv_type == DNS_SRV_WIN2000 ) {
				err = dns_add_rrec(req, rec, &req->num_answers,
						   &req->answers);
			} else {
				err = dns_add_rrec(req, rec, &req->num_additionals,
						   &req->additionals);
			}
			
			if (!ERR_DNS_IS_OK(err)) goto error;

			err = dns_marshall_request(req, req, &buf);
			if (!ERR_DNS_IS_OK(err)) goto error;

			err = dns_send(conn, buf);
			if (!ERR_DNS_IS_OK(err)) goto error;

			TALLOC_FREE(req);
		}

		gss_release_buffer(&minor, &output_desc);

		if ((major != GSS_S_COMPLETE) &&
		    (major != GSS_S_CONTINUE_NEEDED)) {
			return ERROR_DNS_GSS_ERROR;
		}

		if (major == GSS_S_CONTINUE_NEEDED) {

			struct dns_request *resp;
			struct dns_buffer *buf;
			struct dns_tkey_record *tkey;

			err = dns_receive(mem_ctx, conn, &buf);
			if (!ERR_DNS_IS_OK(err)) goto error;

			err = dns_unmarshall_request(buf, buf, &resp);
			if (!ERR_DNS_IS_OK(err)) goto error;

			/*
			 * TODO: Compare id and keyname
			 */
			
			if ((resp->num_additionals != 1) ||
			    (resp->num_answers == 0) ||
			    (resp->answers[0]->type != QTYPE_TKEY)) {
				err = ERROR_DNS_INVALID_MESSAGE;
				goto error;
			}

			err = dns_unmarshall_tkey_record(
				mem_ctx, resp->answers[0], &tkey);
			if (!ERR_DNS_IS_OK(err)) goto error;

			input_desc.length = tkey->key_length;
			input_desc.value = talloc_move(mem_ctx, &tkey->key);

			input_ptr = &input_desc;

			TALLOC_FREE(buf);
		}

	} while ( major == GSS_S_CONTINUE_NEEDED );

	/* If we arrive here, we have a valid security context */

	err = ERROR_DNS_SUCCESS;

      error:

	return err;
}
Beispiel #3
0
DNS_ERROR dns_sign_update(struct dns_update_request *req,
			  gss_ctx_id_t gss_ctx,
			  const char *keyname,
			  const char *algorithmname,
			  time_t time_signed, uint16 fudge)
{
	struct dns_buffer *buf;
	DNS_ERROR err;
	struct dns_domain_name *key, *algorithm;
	struct gss_buffer_desc_struct msg, mic;
	OM_uint32 major, minor;
	struct dns_rrec *rec;

	err = dns_marshall_update_request(req, req, &buf);
	if (!ERR_DNS_IS_OK(err)) return err;

	err = dns_domain_name_from_string(buf, keyname, &key);
	if (!ERR_DNS_IS_OK(err)) goto error;

	err = dns_domain_name_from_string(buf, algorithmname, &algorithm);
	if (!ERR_DNS_IS_OK(err)) goto error;

	dns_marshall_domain_name(buf, key);
	dns_marshall_uint16(buf, DNS_CLASS_ANY);
	dns_marshall_uint32(buf, 0); /* TTL */
	dns_marshall_domain_name(buf, algorithm);
	dns_marshall_uint16(buf, 0); /* Time prefix for 48-bit time_t */
	dns_marshall_uint32(buf, time_signed);
	dns_marshall_uint16(buf, fudge);
	dns_marshall_uint16(buf, 0); /* error */
	dns_marshall_uint16(buf, 0); /* other len */

	err = buf->error;
	if (!ERR_DNS_IS_OK(buf->error)) goto error;

	msg.value = (void *)buf->data;
	msg.length = buf->offset;

	major = gss_get_mic(&minor, gss_ctx, 0, &msg, &mic);
	if (major != 0) {
		err = ERROR_DNS_GSS_ERROR;
		goto error;
	}

	if (mic.length > 0xffff) {
		gss_release_buffer(&minor, &mic);
		err = ERROR_DNS_GSS_ERROR;
		goto error;
	}

	err = dns_create_tsig_record(buf, keyname, algorithmname, time_signed,
				     fudge, mic.length, (uint8 *)mic.value,
				     req->id, 0, &rec);
	gss_release_buffer(&minor, &mic);
	if (!ERR_DNS_IS_OK(err)) goto error;

	err = dns_add_rrec(req, rec, &req->num_additionals, &req->additionals);

 error:
	TALLOC_FREE(buf);
	return err;
}