コード例 #1
0
ファイル: svcctl.c プロジェクト: gojdic/samba
static bool test_QueryServiceConfig2W(struct torture_context *tctx, struct dcerpc_pipe *p)
{
	struct svcctl_QueryServiceConfig2W r;
	struct policy_handle h, s;
	NTSTATUS status;

	uint32_t info_level = SERVICE_CONFIG_DESCRIPTION;
	uint8_t *buffer;
	uint32_t offered = 0;
	uint32_t needed = 0;

	if (!test_OpenSCManager(p, tctx, &h))
		return false;

	if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
		return false;

	buffer = talloc(tctx, uint8_t);

	r.in.handle = &s;
	r.in.info_level = info_level;
	r.in.offered = offered;
	r.out.buffer = buffer;
	r.out.needed = &needed;

	status = dcerpc_svcctl_QueryServiceConfig2W(p, tctx, &r);
	torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");

	if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
		r.in.offered = needed;
		buffer = talloc_array(tctx, uint8_t, needed);
		r.out.buffer = buffer;

		status = dcerpc_svcctl_QueryServiceConfig2W(p, tctx, &r);
		torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
		torture_assert_werr_ok(tctx, r.out.result, "QueryServiceConfig2W failed!");
	}

	r.in.info_level = SERVICE_CONFIG_FAILURE_ACTIONS;
	r.in.offered = offered;
	r.out.buffer = buffer;
	r.out.needed = &needed;

	status = dcerpc_svcctl_QueryServiceConfig2W(p, tctx, &r);
	torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");

	if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
		r.in.offered = needed;
		buffer = talloc_array(tctx, uint8_t, needed);
		r.out.buffer = buffer;

		status = dcerpc_svcctl_QueryServiceConfig2W(p, tctx, &r);
		torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
		torture_assert_werr_ok(tctx, r.out.result, "QueryServiceConfig2W failed!");
	}

	if (!test_CloseServiceHandle(p, tctx, &s))
		return false;

	if (!test_CloseServiceHandle(p, tctx, &h))
		return false;

	return true;
}
コード例 #2
0
ファイル: cmd_eventlog.c プロジェクト: Alexandr-Galko/samba
static NTSTATUS cmd_eventlog_readlog(struct rpc_pipe_client *cli,
				     TALLOC_CTX *mem_ctx,
				     int argc,
				     const char **argv)
{
	NTSTATUS status = NT_STATUS_OK;
	NTSTATUS result = NT_STATUS_OK;
	struct policy_handle handle;
	struct dcerpc_binding_handle *b = cli->binding_handle;

	uint32_t flags = EVENTLOG_BACKWARDS_READ |
			 EVENTLOG_SEQUENTIAL_READ;
	uint32_t offset = 0;
	uint32_t number_of_bytes = 0;
	uint8_t *data = NULL;
	uint32_t sent_size = 0;
	uint32_t real_size = 0;

	if (argc < 2 || argc > 4) {
		printf("Usage: %s logname [offset] [number_of_bytes]\n", argv[0]);
		return NT_STATUS_OK;
	}

	if (argc >= 3) {
		offset = atoi(argv[2]);
	}

	if (argc >= 4) {
		number_of_bytes = atoi(argv[3]);
		data = talloc_array(mem_ctx, uint8_t, number_of_bytes);
		if (!data) {
			goto done;
		}
	}

	status = get_eventlog_handle(cli, mem_ctx, argv[1], &handle);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	do {

		enum ndr_err_code ndr_err;
		DATA_BLOB blob;
		struct EVENTLOGRECORD r;
		uint32_t size = 0;
		uint32_t pos = 0;

		status = dcerpc_eventlog_ReadEventLogW(b, mem_ctx,
						       &handle,
						       flags,
						       offset,
						       number_of_bytes,
						       data,
						       &sent_size,
						       &real_size,
						       &result);
		if (!NT_STATUS_IS_OK(status)) {
			return status;
		}
		if (NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL) &&
		    real_size > 0 ) {
			number_of_bytes = real_size;
			data = talloc_array(mem_ctx, uint8_t, real_size);
			if (!data) {
				goto done;
			}
			status = dcerpc_eventlog_ReadEventLogW(b, mem_ctx,
							       &handle,
							       flags,
							       offset,
							       number_of_bytes,
							       data,
							       &sent_size,
							       &real_size,
							       &result);
			if (!NT_STATUS_IS_OK(status)) {
				return status;
			}
		}

		if (!NT_STATUS_EQUAL(result, NT_STATUS_END_OF_FILE) &&
		    !NT_STATUS_IS_OK(result)) {
			goto done;
		}

		number_of_bytes = 0;

		size = IVAL(data, pos);

		while (size > 0) {

			blob = data_blob_const(data + pos, size);
			/* dump_data(0, blob.data, blob.length); */
			ndr_err = ndr_pull_struct_blob_all(&blob, mem_ctx, &r,
					   (ndr_pull_flags_fn_t)ndr_pull_EVENTLOGRECORD);
			if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
				status = ndr_map_error2ntstatus(ndr_err);
				goto done;
			}

			NDR_PRINT_DEBUG(EVENTLOGRECORD, &r);

			pos += size;

			if (pos + 4 > sent_size) {
				break;
			}

			size = IVAL(data, pos);
		}

		offset++;

	} while (NT_STATUS_IS_OK(result));

 done:
	dcerpc_eventlog_CloseEventLog(b, mem_ctx, &handle, &result);

	return status;
}
コード例 #3
0
ファイル: net_rpc_service.c プロジェクト: 0x24bin/winexe-1
static NTSTATUS rpc_service_list_internal(struct net_context *c,
					const DOM_SID *domain_sid,
					const char *domain_name,
					struct cli_state *cli,
					struct rpc_pipe_client *pipe_hnd,
					TALLOC_CTX *mem_ctx,
					int argc,
					const char **argv )
{
	struct policy_handle hSCM;
	struct ENUM_SERVICE_STATUSW *services = NULL;
	WERROR result = WERR_GENERAL_FAILURE;
	NTSTATUS status;
	int i;

	uint8_t *buffer = NULL;
	uint32_t buf_size = 0;
	uint32_t bytes_needed = 0;
	uint32_t num_services = 0;
	uint32_t resume_handle = 0;

	if (argc != 0 ) {
		d_printf(_("Usage: net rpc service list\n"));
		return NT_STATUS_OK;
	}

	status = rpccli_svcctl_OpenSCManagerW(pipe_hnd, mem_ctx,
					      pipe_hnd->srv_name_slash,
					      NULL,
					      SC_RIGHT_MGR_ENUMERATE_SERVICE,
					      &hSCM,
					      &result);
	if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
		d_fprintf(stderr,
			  _("Failed to open Service Control Manager. [%s]\n"),
			  win_errstr(result));
		return werror_to_ntstatus(result);
	}

	do {
		status = rpccli_svcctl_EnumServicesStatusW(pipe_hnd, mem_ctx,
							   &hSCM,
							   SERVICE_TYPE_WIN32,
							   SERVICE_STATE_ALL,
							   buffer,
							   buf_size,
							   &bytes_needed,
							   &num_services,
							   &resume_handle,
							   &result);

		if (NT_STATUS_IS_ERR(status)) {
			d_fprintf(stderr,
				_("Failed to enumerate services.  [%s]\n"),
				win_errstr(result));
			break;
		}

		if (W_ERROR_EQUAL(result, WERR_MORE_DATA) && bytes_needed > 0) {
			buffer = talloc_array(mem_ctx, uint8_t, bytes_needed);
			buf_size = bytes_needed;
			continue;
		}

		if ( num_services == 0 ) {
			d_printf(_("No services returned\n"));
			break;
		}

		{
			enum ndr_err_code ndr_err;
			DATA_BLOB blob;
			struct ndr_pull *ndr;

			blob.length = buf_size;
			blob.data = talloc_steal(mem_ctx, buffer);

			services = talloc_array(mem_ctx, struct ENUM_SERVICE_STATUSW, num_services);
			if (!services) {
				status = NT_STATUS_NO_MEMORY;
				break;
			}

			ndr = ndr_pull_init_blob(&blob, mem_ctx, NULL);
			if (ndr == NULL) {
				status = NT_STATUS_NO_MEMORY;
				break;
			}

			ndr_err = ndr_pull_ENUM_SERVICE_STATUSW_array(
				ndr, num_services, services);
			if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
				status = ndr_map_error2ntstatus(ndr_err);
				break;
			}

			for ( i=0; i<num_services; i++ ) {
				d_printf("%-20s    \"%s\"\n",
					services[i].service_name,
					services[i].display_name);
			}
		}

	} while (W_ERROR_EQUAL(result, WERR_MORE_DATA));

	rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hSCM, NULL);

	return status;
}
コード例 #4
0
ファイル: eap_tls.c プロジェクト: mommel/freeradius-server
/*
 *	Frame the Dirty data that needs to be send to the client in an
 *	EAP-Request.  We always embed the TLS-length in all EAP-TLS
 *	packets that we send, for easy reference purpose.  Handle
 *	fragmentation and sending the next fragment etc.
 */
int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn)
{
	EAPTLS_PACKET	reply;
	unsigned int	size;
	unsigned int 	nlen;
	unsigned int 	lbit = 0;

	/* This value determines whether we set (L)ength flag for
		EVERY packet we send and add corresponding
		"TLS Message Length" field.

	length_flag = true;
		This means we include L flag and "TLS Msg Len" in EVERY
		packet we send out.

	length_flag = false;
		This means we include L flag and "TLS Msg Len" **ONLY**
		in First packet of a fragment series. We do not use
		it anywhere else.

		Having L flag in every packet is prefered.

	*/
	if (ssn->length_flag) {
		lbit = 4;
	}
	if (ssn->fragment == 0) {
		ssn->tls_msg_len = ssn->dirty_out.used;
	}

	reply.code = FR_TLS_REQUEST;
	reply.flags = ssn->peap_flag;

	/* Send data, NOT more than the FRAGMENT size */
	if (ssn->dirty_out.used > ssn->offset) {
		size = ssn->offset;
		reply.flags = SET_MORE_FRAGMENTS(reply.flags);
		/* Length MUST be included if it is the First Fragment */
		if (ssn->fragment == 0) {
			lbit = 4;
		}
		ssn->fragment = 1;
	} else {
		size = ssn->dirty_out.used;
		ssn->fragment = 0;
	}

	reply.dlen = lbit + size;
	reply.length = TLS_HEADER_LEN + 1/*flags*/ + reply.dlen;

	reply.data = talloc_array(eap_ds, uint8_t, reply.length);
	if (!reply.data) return 0;

	if (lbit) {
		nlen = htonl(ssn->tls_msg_len);
		memcpy(reply.data, &nlen, lbit);
		reply.flags = SET_LENGTH_INCLUDED(reply.flags);
	}
	(ssn->record_minus)(&ssn->dirty_out, reply.data + lbit, size);

	eaptls_compose(eap_ds, &reply);
	talloc_free(reply.data);
	reply.data = NULL;

	return 1;
}
コード例 #5
0
ファイル: tcp.c プロジェクト: AlainRomeyer/freeradius-server
/*
 *	Receives a packet, assuming that the RADIUS_PACKET structure
 *	has been filled out already.
 *
 *	This ASSUMES that the packet is allocated && fields
 *	initialized.
 *
 *	This ASSUMES that the socket is marked as O_NONBLOCK, which
 *	the function above does set, if your system supports it.
 *
 *	Calling this function MAY change sockfd,
 *	if src_ipaddr.af == AF_UNSPEC.
 */
int fr_tcp_read_packet(RADIUS_PACKET *packet, int flags)
{
	ssize_t len;

	/*
	 *	No data allocated.  Read the 4-byte header into
	 *	a temporary buffer.
	 */
	if (!packet->data) {
		int packet_len;

		len = recv(packet->sockfd, packet->vector + packet->data_len,
			   4 - packet->data_len, 0);
		if (len == 0) return -2; /* clean close */

#ifdef ECONNRESET
		if ((len < 0) && (errno == ECONNRESET)) { /* forced */
			return -2;
		}
#endif

		if (len < 0) {
			fr_strerror_printf("Error receiving packet: %s", fr_syserror(errno));
			return -1;
		}

		packet->data_len += len;
		if (packet->data_len < 4) { /* want more data */
			return 0;
		}

		packet_len = (packet->vector[2] << 8) | packet->vector[3];

		if (packet_len < AUTH_HDR_LEN) {
			fr_strerror_printf("Discarding packet: Smaller than RFC minimum of 20 bytes");
			return -1;
		}

		/*
		 *	If the packet is too big, then the socket is bad.
		 */
		if (packet_len > MAX_PACKET_LEN) {
			fr_strerror_printf("Discarding packet: Larger than RFC limitation of 4096 bytes");
			return -1;
		}

		packet->data = talloc_array(packet, uint8_t, packet_len);
		if (!packet->data) {
			fr_strerror_printf("Out of memory");
			return -1;
		}

		packet->data_len = packet_len;
		packet->partial = 4;
		memcpy(packet->data, packet->vector, 4);
	}

	/*
	 *	Try to read more data.
	 */
	len = recv(packet->sockfd, packet->data + packet->partial,
		   packet->data_len - packet->partial, 0);
	if (len == 0) return -2; /* clean close */

#ifdef ECONNRESET
	if ((len < 0) && (errno == ECONNRESET)) { /* forced */
		return -2;
	}
#endif

	if (len < 0) {
		fr_strerror_printf("Error receiving packet: %s", fr_syserror(errno));
		return -1;
	}

	packet->partial += len;

	if (packet->partial < packet->data_len) {
		return 0;
	}

	/*
	 *	See if it's a well-formed RADIUS packet.
	 */
	if (!rad_packet_ok(packet, flags, NULL)) {
		return -1;
	}

	/*
	 *	Explicitly set the VP list to empty.
	 */
	packet->vps = NULL;

	if (fr_debug_flag) {
		char ip_buf[128], buffer[256];

		if (packet->src_ipaddr.af != AF_UNSPEC) {
			inet_ntop(packet->src_ipaddr.af,
				  &packet->src_ipaddr.ipaddr,
				  ip_buf, sizeof(ip_buf));
			snprintf(buffer, sizeof(buffer), "host %s port %d",
				 ip_buf, packet->src_port);
		} else {
			snprintf(buffer, sizeof(buffer), "socket %d",
				 packet->sockfd);
		}


		if ((packet->code > 0) && (packet->code < FR_MAX_PACKET_CODE)) {
			DEBUG("rad_recv: %s packet from %s",
			      fr_packet_codes[packet->code], buffer);
		} else {
			DEBUG("rad_recv: Packet from %s code=%d",
			      buffer, packet->code);
		}
		DEBUG(", id=%d, length=%zu\n", packet->id, packet->data_len);
	}

	return 1;		/* done reading the packet */
}
コード例 #6
0
static int sendrecv_eap(RADIUS_PACKET *rep)
{
	RADIUS_PACKET *req = NULL;
	VALUE_PAIR *vp, *vpnext;
	int tried_eap_md5 = 0;

	if (!rep) return -1;

	/*
	 *	Keep a copy of the the User-Password attribute.
	 */
	if ((vp = pairfind(rep->vps, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) != NULL) {
		strlcpy(password, vp->vp_strvalue, sizeof(password));

	} else 	if ((vp = pairfind(rep->vps, PW_USER_PASSWORD, 0, TAG_ANY)) != NULL) {
		strlcpy(password, vp->vp_strvalue, sizeof(password));
		/*
		 *	Otherwise keep a copy of the CHAP-Password attribute.
		 */
	} else if ((vp = pairfind(rep->vps, PW_CHAP_PASSWORD, 0, TAG_ANY)) != NULL) {
		strlcpy(password, vp->vp_strvalue, sizeof(password));
	} else {
		*password = '******';
	}

 again:
	rep->id++;

	/*
	 * if there are EAP types, encode them into an EAP-Message
	 *
	 */
	map_eap_methods(rep);

	/*
	 *  Fix up Digest-Attributes issues
	 */
	for (vp = rep->vps; vp != NULL; vp = vp->next) {
		switch (vp->da->attr) {
		default:
			break;

		case PW_DIGEST_REALM:
		case PW_DIGEST_NONCE:
		case PW_DIGEST_METHOD:
		case PW_DIGEST_URI:
		case PW_DIGEST_QOP:
		case PW_DIGEST_ALGORITHM:
		case PW_DIGEST_BODY_DIGEST:
		case PW_DIGEST_CNONCE:
		case PW_DIGEST_NONCE_COUNT:
		case PW_DIGEST_USER_NAME:
			/* overlapping! */
			{
				DICT_ATTR const *da;
				uint8_t *p, *q;

				p = talloc_array(vp, uint8_t, vp->length + 2);

				memcpy(p + 2, vp->vp_octets, vp->length);
				p[0] = vp->da->attr - PW_DIGEST_REALM + 1;
				vp->length += 2;
				p[1] = vp->length;

				da = dict_attrbyvalue(PW_DIGEST_ATTRIBUTES, 0);
				vp->da = da;

				/*
				 *	Re-do pairmemsteal ourselves,
				 *	because we play games with
				 *	vp->da, and pairmemsteal goes
				 *	to GREAT lengths to sanitize
				 *	and fix and change and
				 *	double-check the various
				 *	fields.
				 */
				memcpy(&q, &vp->vp_octets, sizeof(q));
				talloc_free(q);

				vp->vp_octets = talloc_steal(vp, p);
				vp->type = VT_DATA;

				VERIFY_VP(vp);
			}
			break;
		}
	}

	/*
	 *	If we've already sent a packet, free up the old
	 *	one, and ensure that the next packet has a unique
	 *	ID and authentication vector.
	 */
	if (rep->data) {
		talloc_free(rep->data);
		rep->data = NULL;
	}

	fr_md5_calc(rep->vector, rep->vector,
			sizeof(rep->vector));

	if (*password != '\0') {
		if ((vp = pairfind(rep->vps, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) != NULL) {
			pairstrcpy(vp, password);

		} else if ((vp = pairfind(rep->vps, PW_USER_PASSWORD, 0, TAG_ANY)) != NULL) {
			pairstrcpy(vp, password);

		} else if ((vp = pairfind(rep->vps, PW_CHAP_PASSWORD, 0, TAG_ANY)) != NULL) {
			pairstrcpy(vp, password);

			uint8_t *p;
			p = talloc_zero_array(vp, uint8_t, 17);
			rad_chap_encode(rep, p, rep->id, vp);
			pairmemsteal(vp, p);
		}
	} /* there WAS a password */

	/* send the response, wait for the next request */
	send_packet(rep, &req);

	if (!req) return -1;

	/* okay got back the packet, go and decode the EAP-Message. */
	unmap_eap_methods(req);

	debug_packet(req, R_RECV);

	/* now look for the code type. */
	for (vp = req->vps; vp != NULL; vp = vpnext) {
		vpnext = vp->next;

		switch (vp->da->attr) {
		default:
			break;

		case ATTRIBUTE_EAP_BASE+PW_EAP_MD5:
			if(respond_eap_md5(req, rep) && tried_eap_md5 < 3)
			{
				tried_eap_md5++;
				goto again;
			}
			break;

		case ATTRIBUTE_EAP_BASE+PW_EAP_SIM:
			if(respond_eap_sim(req, rep))
			{
				goto again;
			}
			break;
		}
	}

	return 1;
}
コード例 #7
0
int proxy_tls_recv(rad_listen_t *listener)
{
	int rcode;
	size_t length;
	listen_socket_t *sock = listener->data;
	char buffer[256];
	RADIUS_PACKET *packet;
	uint8_t *data;

	/*
	 *	Get the maximum size of data to receive.
	 */
	if (!sock->data) sock->data = talloc_array(sock, uint8_t,
						   sock->ssn->offset);
	data = sock->data;

	DEBUG3("Proxy SSL socket has data to read");
	PTHREAD_MUTEX_LOCK(&sock->mutex);
redo:
	rcode = SSL_read(sock->ssn->ssl, data, 4);
	if (rcode <= 0) {
		int err = SSL_get_error(sock->ssn->ssl, rcode);
		switch (err) {
		case SSL_ERROR_WANT_READ:
		case SSL_ERROR_WANT_WRITE:
			goto redo;

		case SSL_ERROR_ZERO_RETURN:
			/* remote end sent close_notify, send one back */
			SSL_shutdown(sock->ssn->ssl);

		case SSL_ERROR_SYSCALL:
		do_close:
			PTHREAD_MUTEX_UNLOCK(&sock->mutex);
			tls_socket_close(listener);
			return 0;

		default:
			while ((err = ERR_get_error())) {
				DEBUG("proxy recv says %s",
				      ERR_error_string(err, NULL));
			}

			goto do_close;
		}
	}

	length = (data[2] << 8) | data[3];
	DEBUG3("Proxy received header saying we have a packet of %u bytes",
	       (unsigned int) length);

	if (length > sock->ssn->offset) {
		INFO("Received packet will be too large! Set \"fragment_size=%u\"",
		       (data[2] << 8) | data[3]);
		goto do_close;
	}

	rcode = SSL_read(sock->ssn->ssl, data + 4, length);
	if (rcode <= 0) {
		switch (SSL_get_error(sock->ssn->ssl, rcode)) {
		case SSL_ERROR_WANT_READ:
		case SSL_ERROR_WANT_WRITE:
			break;

		case SSL_ERROR_ZERO_RETURN:
			/* remote end sent close_notify, send one back */
			SSL_shutdown(sock->ssn->ssl);
			goto do_close;
		default:
			goto do_close;
		}
	}
	PTHREAD_MUTEX_UNLOCK(&sock->mutex);

	packet = rad_alloc(NULL, 0);
	packet->sockfd = listener->fd;
	packet->src_ipaddr = sock->other_ipaddr;
	packet->src_port = sock->other_port;
	packet->dst_ipaddr = sock->my_ipaddr;
	packet->dst_port = sock->my_port;
	packet->code = data[0];
	packet->id = data[1];
	packet->data_len = length;
	packet->data = talloc_array(packet, uint8_t, packet->data_len);
	memcpy(packet->data, data, packet->data_len);
	memcpy(packet->vector, packet->data + 4, 16);

	/*
	 *	FIXME: Client MIB updates?
	 */
	switch(packet->code) {
	case PW_CODE_AUTHENTICATION_ACK:
	case PW_CODE_ACCESS_CHALLENGE:
	case PW_CODE_AUTHENTICATION_REJECT:
		break;

#ifdef WITH_ACCOUNTING
	case PW_CODE_ACCOUNTING_RESPONSE:
		break;
#endif

	default:
		/*
		 *	FIXME: Update MIB for packet types?
		 */
		ERROR("Invalid packet code %d sent to a proxy port "
		       "from home server %s port %d - ID %d : IGNORED",
		       packet->code,
		       ip_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)),
		       packet->src_port, packet->id);
		rad_free(&packet);
		return 0;
	}

	if (!request_proxy_reply(packet)) {
		rad_free(&packet);
		return 0;
	}

	return 1;
}
コード例 #8
0
ファイル: rlm_soh.c プロジェクト: geaaru/freeradius-server
static rlm_rcode_t CC_HINT(nonnull) mod_post_auth(void *instance, UNUSED void *thread, REQUEST *request)
{
#ifdef WITH_DHCP
	int			rcode;
	VALUE_PAIR		*vp;
	rlm_soh_t const		*inst = instance;

	if (!inst->dhcp) return RLM_MODULE_NOOP;

	vp = fr_pair_find_by_da(request->packet->vps, attr_dhcp_vendor, TAG_ANY);
	if (vp) {
		/*
		 * vendor-specific options contain
		 *
		 * vendor opt 220/0xdc - SoH payload, or null byte to probe, or string
		 * "NAP" to indicate server-side support for SoH in OFFERs
		 *
		 * vendor opt 222/0xde - SoH correlation ID as utf-16 string, yuck...
		 */
		uint8_t vopt, vlen;
		uint8_t const *data;

		data = vp->vp_octets;
		while (data < vp->vp_octets + vp->vp_length) {
			vopt = *data++;
			vlen = *data++;
			switch (vopt) {
			case 220:
				if (vlen <= 1) {
					uint8_t *p;

					RDEBUG2("SoH adding NAP marker to DHCP reply");
					/* client probe; send "NAP" in the reply */
					vp = fr_pair_afrom_da(request->reply, attr_dhcp_vendor);
					p = talloc_array(vp, uint8_t, 5);
					p[0] = 220;
					p[1] = 3;
					p[4] = 'N';
					p[3] = 'A';
					p[2] = 'P';
					fr_pair_value_memsteal(vp, p);
					fr_pair_add(&request->reply->vps, vp);

				} else {
					RDEBUG2("SoH decoding NAP from DHCP request");
					/* SoH payload */
					rcode = soh_verify(request, data, vlen);
					if (rcode < 0) {
						return RLM_MODULE_FAIL;
					}
				}
				break;

			default:
				/* nothing to do */
				break;
			}
			data += vlen;
		}
		return RLM_MODULE_OK;
	}
#endif
	return RLM_MODULE_NOOP;
}
コード例 #9
0
ファイル: chkregf.c プロジェクト: bitlair/chkregf
struct hbin_data_block *get_hbin_data_block(TALLOC_CTX *mem_ctx, FILE *fd, long int offset, long int parent_off)
{
	struct hbin_data_block *block;
	long int cur_offset;

	block = talloc_zero(mem_ctx, struct hbin_data_block);

	/* [SYN] Set index to data block */
	cur_offset = offset+0x1000;

	/* [SYN] Seek to data block */
	fseek(fd, cur_offset, SEEK_SET);

#if DODEBUG > 2
	printf("Debug: Parsing block at cur_offset 0x%lx, parent 0x%lx\n", (long)cur_offset, (long) parent_off+0x1000);
#endif
	if (!fread(block, 4, 1, fd)) {
		printf("Error: short read while reading hbin data record size at 0x%lx\n",
				(long)cur_offset);
		return NULL;
	}
	if (block->size > 0) {
		if (parent_off > 0) {
			/* [SYN] Positive block->size means unused. Time to barf. */
			printf("Error: Referencing unused block (0x%lx) with size 0x%lx from 0x%lx\n",
					(long)cur_offset, (long)block->size, (long)parent_off);
			return NULL;
		} else {
			block->size = -block->size;
			return block;
		}
	}
	if (block->size == 0) {
		printf("Error: hbin data record size is NULL at 0x%lx\n",
				(long)cur_offset);
		return NULL;
	}
		
	block->size = -block->size;
	
	/* [SYN] Check block->size, do not allocate it if bigger */
	if (block->size > 32768) {
		printf("Warning: hbin data record size (0x%lx) is quite large at 0x%lx\n",
				(long)block->size, (long)cur_offset);
		printf("Warning: NOT ALLOCATING THIS BLOCK.");
		return NULL;
	}
		
	/* [SYN] Allocate memory and read the record into memory */
	if ((block->data = talloc_array(block, uint8_t, block->size)) == NULL) {
		printf("Failed to allocate %ld bytes at record 0x%lx\n",
				(long)block->size, (long)cur_offset);
		return NULL;
	}
	if (!fread(block->data, block->size, 1, fd)) {
		printf("Error: Failed to read hbin data record at 0x%lx\n",
				(long)cur_offset);
		return NULL;
	}
	return block;

}
コード例 #10
0
ファイル: rlm_eap_md5.c プロジェクト: janetuk/freeradius
/*
 *	Initiate the EAP-MD5 session by sending a challenge to the peer.
 */
static int mod_session_init(UNUSED void *instance, eap_handler_t *handler)
{
	int		i;
	MD5_PACKET	*reply;
	REQUEST		*request = handler->request;

	/*
	 *	Allocate an EAP-MD5 packet.
	 */
	reply = talloc(handler, MD5_PACKET);
	if (!reply)  {
		return 0;
	}

	/*
	 *	Fill it with data.
	 */
	reply->code = PW_MD5_CHALLENGE;
	reply->length = 1 + MD5_CHALLENGE_LEN; /* one byte of value size */
	reply->value_size = MD5_CHALLENGE_LEN;

	/*
	 *	Allocate user data.
	 */
	reply->value = talloc_array(reply, uint8_t, reply->value_size);
	if (!reply->value) {
		talloc_free(reply);
		return 0;
	}

	/*
	 *	Get a random challenge.
	 */
	for (i = 0; i < reply->value_size; i++) {
		reply->value[i] = fr_rand();
	}
	RDEBUG2("Issuing MD5 Challenge");

	/*
	 *	Keep track of the challenge.
	 */
	handler->opaque = talloc_array(handler, uint8_t, reply->value_size);
	rad_assert(handler->opaque != NULL);
	memcpy(handler->opaque, reply->value, reply->value_size);
	handler->free_opaque = NULL;

	/*
	 *	Compose the EAP-MD5 packet out of the data structure,
	 *	and free it.
	 */
	eapmd5_compose(handler->eap_ds, reply);

	/*
	 *	We don't need to authorize the user at this point.
	 *
	 *	We also don't need to keep the challenge, as it's
	 *	stored in 'handler->eap_ds', which will be given back
	 *	to us...
	 */
	handler->stage = PROCESS;

	return 1;
}
コード例 #11
0
ファイル: drs_util.c プロジェクト: Arkhont/samba
/**
 * Decode Attribute OID based on MS documentation
 * See MS-DRSR.pdf - 5.16.4
 *
 * On success returns decoded OID and
 * corresponding prefix_map index (if requested)
 */
bool drs_util_oid_from_attid(struct torture_context *tctx,
			     const struct drsuapi_DsReplicaOIDMapping_Ctr *prefix_map,
			     uint32_t attid,
			     const char **_oid,
			     int *map_idx)
{
	int i;
	uint32_t hi_word, lo_word;
	DATA_BLOB bin_oid = {NULL, 0};
	char *oid;
	struct drsuapi_DsReplicaOIDMapping *map_entry = NULL;
	TALLOC_CTX *mem_ctx = talloc_named(tctx, 0, "util_drsuapi_oid_from_attid");

	/* crack attid value */
	hi_word = attid >> 16;
	lo_word = attid & 0xFFFF;

	/* check last entry in the prefix map is the special one */
	map_entry = &prefix_map->mappings[prefix_map->num_mappings-1];
	torture_assert(tctx,
			(map_entry->id_prefix == 0)
			&& (*map_entry->oid.binary_oid == 0xFF),
			"Last entry in Prefix Map is not the special one!");

	/* locate corresponding prefixMap entry */
	map_entry = NULL;
	for (i = 0; i < prefix_map->num_mappings - 1; i++) {

		if (hi_word == prefix_map->mappings[i].id_prefix) {
			map_entry = &prefix_map->mappings[i];
			if (map_idx)	*map_idx = i;
			break;
		}
	}

	torture_assert(tctx, map_entry, "Unable to locate corresponding Prefix Map entry");

	/* copy partial oid making enough room */
	bin_oid.length = map_entry->oid.length + 2;
	bin_oid.data = talloc_array(mem_ctx, uint8_t, bin_oid.length);
	torture_assert(tctx, bin_oid.data, "Not enough memory");
	memcpy(bin_oid.data, map_entry->oid.binary_oid, map_entry->oid.length);

	if (lo_word < 128) {
		bin_oid.length = bin_oid.length - 1;
		bin_oid.data[bin_oid.length-1] = lo_word;
	}
	else {
		if (lo_word >= 32768) {
			lo_word -= 32768;
		}
		bin_oid.data[bin_oid.length-2] = ((lo_word / 128) % 128) + 128; // (0x80 | ((lo_word>>7) & 0x7f))
		bin_oid.data[bin_oid.length-1] = lo_word % 128; // lo_word & 0x7f
	}

	torture_assert(tctx,
			ber_read_OID_String(tctx, bin_oid, &oid),
			"Failed to decode binary OID");
	talloc_free(mem_ctx);

	*_oid = oid;

	return true;
}
コード例 #12
0
ファイル: ipalloc_lcp2.c プロジェクト: encukou/samba
static bool lcp2_init(struct ipalloc_state *ipalloc_state,
		      uint32_t **lcp2_imbalances,
		      bool **rebalance_candidates)
{
	int i, numnodes;
	struct public_ip_list *t;

	numnodes = ipalloc_state->num;

	*rebalance_candidates = talloc_array(ipalloc_state, bool, numnodes);
	if (*rebalance_candidates == NULL) {
		DEBUG(DEBUG_ERR, (__location__ " out of memory\n"));
		return false;
	}
	*lcp2_imbalances = talloc_array(ipalloc_state, uint32_t, numnodes);
	if (*lcp2_imbalances == NULL) {
		DEBUG(DEBUG_ERR, (__location__ " out of memory\n"));
		return false;
	}

	for (i=0; i<numnodes; i++) {
		(*lcp2_imbalances)[i] =
			lcp2_imbalance(ipalloc_state->all_ips, i);
		/* First step: assume all nodes are candidates */
		(*rebalance_candidates)[i] = true;
	}

	/* 2nd step: if a node has IPs assigned then it must have been
	 * healthy before, so we remove it from consideration.  This
	 * is overkill but is all we have because we don't maintain
	 * state between takeover runs.  An alternative would be to
	 * keep state and invalidate it every time the recovery master
	 * changes.
	 */
	for (t = ipalloc_state->all_ips; t != NULL; t = t->next) {
		if (t->pnn != -1) {
			(*rebalance_candidates)[t->pnn] = false;
		}
	}

	/* 3rd step: if a node is forced to re-balance then
	   we allow failback onto the node */
	if (ipalloc_state->force_rebalance_nodes == NULL) {
		return true;
	}
	for (i = 0;
	     i < talloc_array_length(ipalloc_state->force_rebalance_nodes);
	     i++) {
		uint32_t pnn = ipalloc_state->force_rebalance_nodes[i];
		if (pnn >= numnodes) {
			DEBUG(DEBUG_ERR,
			      (__location__ "unknown node %u\n", pnn));
			continue;
		}

		DEBUG(DEBUG_NOTICE,
		      ("Forcing rebalancing of IPs to node %u\n", pnn));
		(*rebalance_candidates)[pnn] = true;
	}

	return true;
}
コード例 #13
0
ファイル: svcctl.c プロジェクト: gojdic/samba
static bool test_EnumDependentServicesW(struct torture_context *tctx,
					struct dcerpc_pipe *p)
{
	struct svcctl_EnumDependentServicesW r;
	struct policy_handle h, s;
	uint32_t needed;
	uint32_t services_returned;
	uint32_t i;
	uint32_t states[] = { SERVICE_STATE_ACTIVE,
			      SERVICE_STATE_INACTIVE,
			      SERVICE_STATE_ALL };

	if (!test_OpenSCManager(p, tctx, &h))
		return false;

	if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
		return false;

	r.in.service = &s;
	r.in.offered = 0;
	r.in.state = 0;
	r.out.service_status = NULL;
	r.out.services_returned = &services_returned;
	r.out.needed = &needed;

	torture_assert_ntstatus_ok(tctx,
		dcerpc_svcctl_EnumDependentServicesW(p, tctx, &r),
		"EnumDependentServicesW failed!");

	torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
		"EnumDependentServicesW failed!");

	for (i=0; i<ARRAY_SIZE(states); i++) {

		r.in.state = states[i];

		torture_assert_ntstatus_ok(tctx,
			dcerpc_svcctl_EnumDependentServicesW(p, tctx, &r),
			"EnumDependentServicesW failed!");

		if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
			r.in.offered = needed;
			r.out.service_status = talloc_array(tctx, uint8_t, needed);

			torture_assert_ntstatus_ok(tctx,
				dcerpc_svcctl_EnumDependentServicesW(p, tctx, &r),
				"EnumDependentServicesW failed!");

		}

		torture_assert_werr_ok(tctx, r.out.result,
			"EnumDependentServicesW failed");
	}

	if (!test_CloseServiceHandle(p, tctx, &s))
		return false;

	if (!test_CloseServiceHandle(p, tctx, &h))
		return false;

	return true;
}
コード例 #14
0
ファイル: svcctl.c プロジェクト: gojdic/samba
static bool test_EnumServicesStatus(struct torture_context *tctx, struct dcerpc_pipe *p)
{
	struct svcctl_EnumServicesStatusW r;
	struct policy_handle h;
	int i;
	NTSTATUS status;
	uint32_t resume_handle = 0;
	struct ENUM_SERVICE_STATUSW *service = NULL;
	uint32_t needed = 0;
	uint32_t services_returned = 0;

	if (!test_OpenSCManager(p, tctx, &h))
		return false;

	r.in.handle = &h;
	r.in.type = SERVICE_TYPE_WIN32;
	r.in.state = SERVICE_STATE_ALL;
	r.in.offered = 0;
	r.in.resume_handle = &resume_handle;
	r.out.service = NULL;
	r.out.resume_handle = &resume_handle;
	r.out.services_returned = &services_returned;
	r.out.needed = &needed;

	status = dcerpc_svcctl_EnumServicesStatusW(p, tctx, &r);

	torture_assert_ntstatus_ok(tctx, status, "EnumServicesStatus failed!");

	if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
		r.in.offered = needed;
		r.out.service = talloc_array(tctx, uint8_t, needed);

		status = dcerpc_svcctl_EnumServicesStatusW(p, tctx, &r);

		torture_assert_ntstatus_ok(tctx, status, "EnumServicesStatus failed!");
		torture_assert_werr_ok(tctx, r.out.result, "EnumServicesStatus failed");
	}

	if (services_returned > 0) {

		enum ndr_err_code ndr_err;
		DATA_BLOB blob;
		struct ndr_pull *ndr;

		blob.length = r.in.offered;
		blob.data = talloc_steal(tctx, r.out.service);

		ndr = ndr_pull_init_blob(&blob, tctx, lp_iconv_convenience(tctx->lp_ctx));

		service = talloc_array(tctx, struct ENUM_SERVICE_STATUSW, services_returned);
		if (!service) {
			return false;
		}

		ndr_err = ndr_pull_ENUM_SERVICE_STATUSW_array(
				ndr, services_returned, service);
		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
			return false;
		}
	}

	for(i = 0; i < services_returned; i++) {

		torture_assert(tctx, service[i].service_name,
			"Service without name returned!");

		printf("%-20s   \"%s\", Type: %d, State: %d\n",
			service[i].service_name, service[i].display_name,
			service[i].status.type, service[i].status.state);
	}

	if (!test_CloseServiceHandle(p, tctx, &h))
		return false;

	return true;
}
コード例 #15
0
ファイル: IStoreFolder.c プロジェクト: EasyLinux/Openchange
/**
   \details Opens a specific message and retrieves a MAPI object that
   can be used to get or set message properties.

   This function opens a specific message defined by a combination of
   object store, folder ID, and message ID and which read/write access
   is defined by ulFlags.

   \param obj_store the store to read from
   \param id_folder the folder ID
   \param id_message the message ID
   \param obj_message the resulting message object
   \param ulFlags

   Possible ulFlags values:
   - 0x0: read only access
   - 0x1: ReadWrite
   - 0x3: Create
   - 0x4: OpenSoftDeleted

   \return MAPI_E_SUCCESS on success, otherwise MAPI error.

   \note Developers may also call GetLastError() to retrieve the last
   MAPI error code. Possible MAPI error codes are:
   - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
   - MAPI_E_INVALID_PARAMETER: obj_store is undefined
   - MAPI_E_CALL_FAILED: A network problem was encountered during the
     transaction

   \sa MAPIInitialize, GetLastError
*/
_PUBLIC_ enum MAPISTATUS OpenMessage(mapi_object_t *obj_store, 
				     mapi_id_t id_folder, 
				     mapi_id_t id_message, 
				     mapi_object_t *obj_message,
				     uint8_t ulFlags)
{
	struct mapi_context		*mapi_ctx;
	struct mapi_request		*mapi_request;
	struct mapi_response		*mapi_response;
	struct EcDoRpc_MAPI_REQ		*mapi_req;
	struct OpenMessage_req		request;
	struct OpenMessage_repl		*reply;
	struct mapi_session		*session;
	mapi_object_message_t		*message;
	struct SPropValue		lpProp;
	const char			*tstring;
	NTSTATUS			status;
	enum MAPISTATUS			retval;
	uint32_t			size = 0;
	TALLOC_CTX			*mem_ctx;
	uint32_t			i = 0;
	uint8_t				logon_id;

	/* Sanity checks */
	OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
	session = mapi_object_get_session(obj_store);
	OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);

	mapi_ctx = session->mapi_ctx;
	OPENCHANGE_RETVAL_IF(!mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);

	if ((retval = mapi_object_get_logon_id(obj_store, &logon_id)) != MAPI_E_SUCCESS)
		return retval;

	mem_ctx = talloc_named(session, 0, "OpenMessage");

	/* Fill the OpenMessage operation */
	request.handle_idx = 0x1;
	request.CodePageId = 0xfff;
	request.FolderId = id_folder;
	request.OpenModeFlags = (enum OpenMessage_OpenModeFlags)ulFlags;
	request.MessageId = id_message;
	size = sizeof (uint8_t) + sizeof(uint16_t) + sizeof(mapi_id_t) + sizeof(uint8_t) + sizeof(mapi_id_t);

	/* Fill the MAPI_REQ request */
	mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
	mapi_req->opnum = op_MAPI_OpenMessage;
	mapi_req->logon_id = logon_id;
	mapi_req->handle_idx = 0;
	mapi_req->u.mapi_OpenMessage = request;
	size += 5;

	/* Fill the mapi_request structure */
	mapi_request = talloc_zero(mem_ctx, struct mapi_request);
	mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
	mapi_request->length = size;
	mapi_request->mapi_req = mapi_req;
	mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
	mapi_request->handles[0] = mapi_object_get_handle(obj_store);
	mapi_request->handles[1] = 0xffffffff;

	status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
	OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
	OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
	retval = mapi_response->mapi_repl->error_code;
	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);

	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);

	/* Set object session and handle */
	mapi_object_set_session(obj_message, session);
	mapi_object_set_handle(obj_message, mapi_response->handles[1]);
	mapi_object_set_logon_id(obj_message, logon_id);

	/* Store OpenMessage reply data */
	reply = &mapi_response->mapi_repl->u.mapi_OpenMessage;

	message = talloc_zero((TALLOC_CTX *)session, mapi_object_message_t);

	tstring = get_TypedString(&reply->SubjectPrefix);
	if (tstring) {
		message->SubjectPrefix = talloc_strdup((TALLOC_CTX *)message, tstring);
	}

	tstring = get_TypedString(&reply->NormalizedSubject);
	if (tstring) {
		message->NormalizedSubject = talloc_strdup((TALLOC_CTX *)message, tstring);
	}
	

	message->cValues = reply->RecipientColumns.cValues;
	message->SRowSet.cRows = reply->RowCount;
	message->SRowSet.aRow = talloc_array((TALLOC_CTX *)message, struct SRow, reply->RowCount + 1);

	message->SPropTagArray.cValues = reply->RecipientColumns.cValues;
	message->SPropTagArray.aulPropTag = talloc_steal(message, reply->RecipientColumns.aulPropTag);

	for (i = 0; i < reply->RowCount; i++) {
		emsmdb_get_SRow((TALLOC_CTX *)message,
				&(message->SRowSet.aRow[i]), &message->SPropTagArray, 
				reply->RecipientRows[i].RecipientRow.prop_count,
				&reply->RecipientRows[i].RecipientRow.prop_values,
				reply->RecipientRows[i].RecipientRow.layout, 1);

		lpProp.ulPropTag = PR_RECIPIENT_TYPE;
		lpProp.value.l = reply->RecipientRows[i].RecipientType;
		SRow_addprop(&(message->SRowSet.aRow[i]), lpProp);

		lpProp.ulPropTag = PR_INTERNET_CPID;
		lpProp.value.l = reply->RecipientRows[i].CodePageId;
		SRow_addprop(&(message->SRowSet.aRow[i]), lpProp);
	}

	/* add SPropTagArray elements we automatically append to SRow */
	SPropTagArray_add((TALLOC_CTX *)message, &message->SPropTagArray, PR_RECIPIENT_TYPE);
	SPropTagArray_add((TALLOC_CTX *)message, &message->SPropTagArray, PR_INTERNET_CPID);

	obj_message->private_data = (void *) message;

	talloc_free(mapi_response);
	talloc_free(mem_ctx);

	return MAPI_E_SUCCESS;
}
コード例 #16
0
ファイル: crypto.c プロジェクト: FreeRADIUS/freeradius-server
int eap_crypto_tls_session_id(TALLOC_CTX *ctx,
#if OPENSSL_VERSION_NUMBER < 0x10101000L
			      UNUSED
#endif
			      REQUEST *request, SSL *ssl,
			      uint8_t **out, uint8_t eap_type,
#if OPENSSL_VERSION_NUMBER < 0x10100000L
			      UNUSED
#endif
			      char const *prf_label,
#if OPENSSL_VERSION_NUMBER < 0x10101000L
			      UNUSED
#endif
			      size_t prf_label_len)
{
	uint8_t		*buff = NULL, *p;

	*out = NULL;

#if OPENSSL_VERSION_NUMBER >= 0x10100000L
	if (!prf_label) goto random_based_session_id;

	switch (SSL_SESSION_get_protocol_version(SSL_get_session(ssl))) {
	case SSL2_VERSION:	/* Should never happen */
	case SSL3_VERSION:	/* Should never happen */
		return - 1;

	case TLS1_VERSION:	/* No Method ID */
	case TLS1_1_VERSION:	/* No Method ID */
	case TLS1_2_VERSION:	/* No Method ID */
	random_based_session_id:
#endif
		MEM(buff = p = talloc_array(ctx, uint8_t, sizeof(eap_type) + (2 * SSL3_RANDOM_SIZE)));
		*p++ = eap_type;

		SSL_get_client_random(ssl, p, SSL3_RANDOM_SIZE);
		p += SSL3_RANDOM_SIZE;
		SSL_get_server_random(ssl, p, SSL3_RANDOM_SIZE);
#if OPENSSL_VERSION_NUMBER >= 0x10101000L
		break;

	/*
	 *	Session-Id = <EAP-Type> || Method-Id
	 *	Method-Id = TLS-Exporter("EXPORTER_EAP_TLS_Method-Id", "", 64)
	 */
	case TLS1_3_VERSION:
	default:
	{
		MEM(buff = p = talloc_array(ctx, uint8_t, sizeof(eap_type) + 64));
		*p++ = eap_type;
		if (SSL_export_keying_material(ssl, p, 64, prf_label, prf_label_len, NULL, 0, 0) != 1) {
			tls_log_error(request, "Failed generating TLS session ID");
			return -1;
		}
	}
		break;
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
	}
#endif
	*out = buff;

	return 0;
}
コード例 #17
0
ファイル: backupkey.c プロジェクト: AIdrifter/samba
static struct bkrp_BackupKey *createRestoreGUIDStruct(struct torture_context *tctx,
				struct dcerpc_pipe *p, int version, DATA_BLOB *out,
				bool norevert,
				bool broken_version,
				bool broken_user,
				bool broken_magic_secret,
				bool broken_magic_access,
				bool broken_hash_access,
				bool broken_cert_guid)
{
	struct dcerpc_binding_handle *b = p->binding_handle;
	struct bkrp_client_side_wrapped data;
	DATA_BLOB *xs;
	DATA_BLOB *sec;
	DATA_BLOB *enc_sec;
	DATA_BLOB *enc_xs;
	DATA_BLOB *blob2;
	DATA_BLOB enc_sec_reverted;
	DATA_BLOB des3_key;
	DATA_BLOB aes_key;
	DATA_BLOB iv;
	DATA_BLOB out_blob;
	struct GUID *guid, *g;
	int t;
	uint32_t size;
	enum ndr_err_code ndr_err;
	NTSTATUS status;
	const char *user;
	struct bkrp_BackupKey *r = createRetreiveBackupKeyGUIDStruct(tctx, p, version, &out_blob);
	if (r == NULL) {
		return NULL;
	}

	if (broken_user) {
		/* we take a fake user*/
		user = "******";
	} else {
		user = cli_credentials_get_username(cmdline_credentials);
	}


	torture_assert_ntstatus_ok(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r),
					"Get GUID");
	/*
	 * We have to set it outside of the function createRetreiveBackupKeyGUIDStruct
	 * the len of the blob, this is due to the fact that they don't have the
	 * same size (one is 32bits the other 64bits)
	 */
	out_blob.length = *r->out.data_out_len;

	sec = create_unencryptedsecret(tctx, broken_magic_secret, version);
	if (sec == NULL) {
		return NULL;
	}

	xs = create_access_check(tctx, p, tctx, user, broken_hash_access, version);
	if (xs == NULL) {
		return NULL;
	}

	if (broken_magic_access){
		/* The start of the access_check structure contains the 
		 * GUID of the certificate
		 */
		xs->data[0]++;
	}

	enc_sec = encrypt_blob_pk(tctx, tctx, out_blob.data, out_blob.length, sec);
	if (!enc_sec) {
		return NULL;
	}
	enc_sec_reverted.data = talloc_array(tctx, uint8_t, enc_sec->length);
	if (enc_sec_reverted.data == NULL) {
		return NULL;
	}
	enc_sec_reverted.length = enc_sec->length;

	/*
	* We DO NOT revert the array on purpose it's in order to check that
	* when the server is not able to decrypt then it answer the correct error
	*/
	if (norevert) {
		for(t=0; t< enc_sec->length; t++) {
			enc_sec_reverted.data[t] = ((uint8_t*)enc_sec->data)[t];
		}
	} else {
		for(t=0; t< enc_sec->length; t++) {
			enc_sec_reverted.data[t] = ((uint8_t*)enc_sec->data)[enc_sec->length - t -1];
		}
	}

	size = sec->length;
	if (version ==2) {
		const AlgorithmIdentifier *alg = hx509_crypto_des_rsdi_ede3_cbc();
		iv.data = sec->data+(size - 8);
		iv.length = 8;

		des3_key.data = sec->data+(size - 32);
		des3_key.length = 24;

		enc_xs = encrypt_blob(tctx, tctx, &des3_key, &iv, xs, alg);
	}
	if (version == 3) {
		const AlgorithmIdentifier *alg = hx509_crypto_aes256_cbc();
		iv.data = sec->data+(size-16);
		iv.length = 16;

		aes_key.data = sec->data+(size-48);
		aes_key.length = 32;

		enc_xs = encrypt_blob(tctx, tctx, &aes_key, &iv, xs, alg);
	}

	if (!enc_xs) {
		return NULL;
	}

	/* To cope with the fact that heimdal do padding at the end for the moment */
	enc_xs->length = xs->length;

	guid = get_cert_guid(tctx, tctx, out_blob.data, out_blob.length);
	if (guid == NULL) {
		return NULL;
	}

	if (broken_version) {
		data.version = 1;
	} else {
		data.version = version;
	}

	data.guid = *guid;
	data.encrypted_secret = enc_sec_reverted.data;
	data.access_check = enc_xs->data;
	data.encrypted_secret_len = enc_sec->length;
	data.access_check_len = enc_xs->length;

	/* We want the blob to persist after this function so we don't
	 * allocate it in the stack
	 */
	blob2 = talloc(tctx, DATA_BLOB);
	if (blob2 == NULL) {
		return NULL;
	}

	ndr_err = ndr_push_struct_blob(blob2, tctx, &data,
			(ndr_push_flags_fn_t)ndr_push_bkrp_client_side_wrapped);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		return NULL;
	}

	if (broken_cert_guid) {
		blob2->data[12]++;
	}

	ZERO_STRUCT(*r);

	g = talloc(tctx, struct GUID);
	if (g == NULL) {
		return NULL;
	}

	status = GUID_from_string(BACKUPKEY_RESTORE_GUID, g);
	if (!NT_STATUS_IS_OK(status)) {
		return NULL;
	}

	r->in.guidActionAgent = g;
	r->in.data_in = blob2->data;
	r->in.data_in_len = blob2->length;
	r->in.param = 0;
	r->out.data_out = &(out->data);
	r->out.data_out_len = talloc(r, uint32_t);
	return r;
}
コード例 #18
0
ファイル: whoami.c プロジェクト: AIdrifter/samba
static bool smb_raw_query_posix_whoami(void *mem_ctx,
				struct torture_context *torture,
				struct smbcli_state *cli,
				struct smb_whoami *whoami,
				unsigned max_data)
{
	struct smb_trans2 tp;
	NTSTATUS status;
	size_t offset;
	int i;

	uint16_t setup = TRANSACT2_QFSINFO;
	uint16_t info_level;

	ZERO_STRUCTP(whoami);

	tp.in.max_setup = 0;
	tp.in.flags = 0;
	tp.in.timeout = 0;
	tp.in.setup_count = 1;
	tp.in.max_param = 10;
	tp.in.max_data = (uint16_t)max_data;
	tp.in.setup = &setup;
	tp.in.trans_name = NULL;
	SSVAL(&info_level, 0, SMB_QFS_POSIX_WHOAMI);
	tp.in.params = data_blob_talloc(mem_ctx, &info_level, 2);
	tp.in.data = data_blob_talloc(mem_ctx, NULL, 0);

	status = smb_raw_trans2(cli->tree, mem_ctx, &tp);
	torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK,
			"doing SMB_QFS_POSIX_WHOAMI");

	/* Make sure we got back all the required fields. */
	torture_assert(torture, tp.out.params.length == 0,
			"trans2 params should be empty");
	torture_assert(torture, tp.out.data.length >= WHOAMI_REQUIRED_SIZE,
			"checking for required response fields");

	whoami->mapping_flags = IVAL(tp.out.data.data, 0);
	whoami->mapping_mask = IVAL(tp.out.data.data, 4);
	whoami->server_uid = BVAL(tp.out.data.data, 8);
	whoami->server_gid = BVAL(tp.out.data.data, 16);
	whoami->num_gids = IVAL(tp.out.data.data, 24);
	whoami->num_sids = IVAL(tp.out.data.data, 28);
	whoami->num_sid_bytes = IVAL(tp.out.data.data, 32);
	whoami->reserved = IVAL(tp.out.data.data, 36);

	/* The GID list and SID list are optional, depending on the count
	 * and length fields.
	 */
	if (whoami->num_sids != 0) {
		torture_assert(torture, whoami->num_sid_bytes != 0,
				"SID count does not match byte count");
	}

	printf("\tmapping_flags=0x%08x mapping_mask=0x%08x\n",
			whoami->mapping_flags, whoami->mapping_mask);
	printf("\tserver UID=%llu GID=%llu\n",
	       (unsigned long long)whoami->server_uid, (unsigned long long)whoami->server_gid);
	printf("\t%u GIDs, %u SIDs, %u SID bytes\n",
			whoami->num_gids, whoami->num_sids,
			whoami->num_sid_bytes);

	offset = WHOAMI_REQUIRED_SIZE;

	torture_assert_int_equal(torture, whoami->reserved, 0,
			"invalid reserved field");

	if (tp.out.data.length == offset) {
		/* No SIDs or GIDs returned */
		torture_assert_int_equal(torture, whoami->num_gids, 0,
				"invalid GID count");
		torture_assert_int_equal(torture, whoami->num_sids, 0,
				"invalid SID count");
		torture_assert_int_equal(torture, whoami->num_sid_bytes, 0,
				"invalid SID byte count");
		return true;
	}

	if (whoami->num_gids != 0) {
		int remain = tp.out.data.length - offset;
		int gid_bytes = whoami->num_gids * 8;

		if (whoami->num_sids == 0) {
			torture_assert_int_equal(torture, remain, gid_bytes,
					"GID count does not match data length");
		} else {
			torture_assert(torture, remain > gid_bytes,
						"invalid GID count");
		}

		whoami->gid_list = talloc_array(mem_ctx, uint64_t, whoami->num_gids);
		torture_assert(torture, whoami->gid_list != NULL, "out of memory");

		torture_comment(torture, "\tGIDs:\n");
		
		for (i = 0; i < whoami->num_gids; ++i) {
			whoami->gid_list[i] = BVAL(tp.out.data.data, offset);
			offset += 8;
			torture_comment(torture, "\t\t%u\n", (unsigned int)whoami->gid_list[i]);
		}
	}

	/* Check if there should be data left for the SID list. */
	if (tp.out.data.length == offset) {
		torture_assert_int_equal(torture, whoami->num_sids, 0,
				"invalid SID count");
		return true;
	}

	/* All the remaining bytes must be the SID list. */
	torture_assert_int_equal(torture,
		whoami->num_sid_bytes, (tp.out.data.length - offset),
		"invalid SID byte count");

	if (whoami->num_sids != 0) {

		whoami->sid_list = talloc_array(mem_ctx, struct dom_sid *,
				whoami->num_sids);
		torture_assert(torture, whoami->sid_list != NULL,
				"out of memory");

		torture_comment(torture, "\tSIDs:\n");

		for (i = 0; i < whoami->num_sids; ++i) {
			if (!whoami_sid_parse(mem_ctx, torture,
					&tp.out.data, &offset,
					&whoami->sid_list[i])) {
				return false;
			}

			torture_comment(torture, "\t\t%s\n",
					dom_sid_string(torture, whoami->sid_list[i]));
		}
	}
コード例 #19
0
static int tls_socket_recv(rad_listen_t *listener)
{
	int doing_init = false;
	ssize_t rcode;
	RADIUS_PACKET *packet;
	REQUEST *request;
	listen_socket_t *sock = listener->data;
	fr_tls_status_t status;
	RADCLIENT *client = sock->client;

	if (!sock->packet) {
		sock->packet = rad_alloc(NULL, 0);
		if (!sock->packet) return 0;

		sock->packet->sockfd = listener->fd;
		sock->packet->src_ipaddr = sock->other_ipaddr;
		sock->packet->src_port = sock->other_port;
		sock->packet->dst_ipaddr = sock->my_ipaddr;
		sock->packet->dst_port = sock->my_port;

		if (sock->request) {
			(void) talloc_steal(sock->request, sock->packet);
			sock->request->packet = sock->packet;
		}
	}

	/*
	 *	Allocate a REQUEST for debugging.
	 */
	if (!sock->request) {
		sock->request = request = request_alloc(NULL);
		if (!sock->request) {
			ERROR("Out of memory");
			return 0;
		}

		rad_assert(request->packet == NULL);
		rad_assert(sock->packet != NULL);
		request->packet = sock->packet;

		request->component = "<core>";
		request->component = "<tls-connect>";

		/*
		 *	Not sure if we should do this on every packet...
		 */
		request->reply = rad_alloc(request, 0);
		if (!request->reply) return 0;

		request->options = RAD_REQUEST_OPTION_DEBUG2;

		rad_assert(sock->ssn == NULL);

		sock->ssn = tls_new_session(listener->tls, sock->request,
					    listener->tls->require_client_cert);
		if (!sock->ssn) {
			request_free(&sock->request);
			sock->packet = NULL;
			return 0;
		}

		(void) talloc_steal(sock, sock->ssn);
		SSL_set_ex_data(sock->ssn->ssl, FR_TLS_EX_INDEX_REQUEST, (void *)request);
		SSL_set_ex_data(sock->ssn->ssl, FR_TLS_EX_INDEX_CERTS, (void *)&request->packet->vps);

		doing_init = true;
	}

	rad_assert(sock->request != NULL);
	rad_assert(sock->request->packet != NULL);
	rad_assert(sock->packet != NULL);
	rad_assert(sock->ssn != NULL);

	request = sock->request;

	RDEBUG3("Reading from socket %d", request->packet->sockfd);
	PTHREAD_MUTEX_LOCK(&sock->mutex);
	rcode = read(request->packet->sockfd,
		     sock->ssn->dirty_in.data,
		     sizeof(sock->ssn->dirty_in.data));
	if ((rcode < 0) && (errno == ECONNRESET)) {
	do_close:
		PTHREAD_MUTEX_UNLOCK(&sock->mutex);
		tls_socket_close(listener);
		return 0;
	}

	if (rcode < 0) {
		RDEBUG("Error reading TLS socket: %s", fr_syserror(errno));
		goto do_close;
	}

	/*
	 *	Normal socket close.
	 */
	if (rcode == 0) goto do_close;

	sock->ssn->dirty_in.used = rcode;

	dump_hex("READ FROM SSL", sock->ssn->dirty_in.data, sock->ssn->dirty_in.used);

	/*
	 *	Catch attempts to use non-SSL.
	 */
	if (doing_init && (sock->ssn->dirty_in.data[0] != handshake)) {
		RDEBUG("Non-TLS data sent to TLS socket: closing");
		goto do_close;
	}

	/*
	 *	Skip ahead to reading application data.
	 */
	if (SSL_is_init_finished(sock->ssn->ssl)) goto app;

	if (!tls_handshake_recv(request, sock->ssn)) {
		RDEBUG("FAILED in TLS handshake receive");
		goto do_close;
	}

	if (sock->ssn->dirty_out.used > 0) {
		tls_socket_write(listener, request);
		PTHREAD_MUTEX_UNLOCK(&sock->mutex);
		return 0;
	}

app:
	/*
	 *	FIXME: Run the packet through a virtual server in
	 *	order to see if we like the certificate presented by
	 *	the client.
	 */

	status = tls_application_data(sock->ssn, request);
	RDEBUG("Application data status %d", status);

	if (status == FR_TLS_MORE_FRAGMENTS) {
		PTHREAD_MUTEX_UNLOCK(&sock->mutex);
		return 0;
	}

	if (sock->ssn->clean_out.used == 0) {
		PTHREAD_MUTEX_UNLOCK(&sock->mutex);
		return 0;
	}

	dump_hex("TUNNELED DATA", sock->ssn->clean_out.data, sock->ssn->clean_out.used);

	/*
	 *	If the packet is a complete RADIUS packet, return it to
	 *	the caller.  Otherwise...
	 */
	if ((sock->ssn->clean_out.used < 20) ||
	    (((sock->ssn->clean_out.data[2] << 8) | sock->ssn->clean_out.data[3]) != (int) sock->ssn->clean_out.used)) {
		RDEBUG("Received bad packet: Length %d contents %d",
		       sock->ssn->clean_out.used,
		       (sock->ssn->clean_out.data[2] << 8) | sock->ssn->clean_out.data[3]);
		goto do_close;
	}

	packet = sock->packet;
	packet->data = talloc_array(packet, uint8_t, sock->ssn->clean_out.used);
	packet->data_len = sock->ssn->clean_out.used;
	sock->ssn->record_minus(&sock->ssn->clean_out, packet->data, packet->data_len);
	packet->vps = NULL;
	PTHREAD_MUTEX_UNLOCK(&sock->mutex);

	if (!rad_packet_ok(packet, 0)) {
		RDEBUG("Received bad packet: %s", fr_strerror());
		tls_socket_close(listener);
		return 0;	/* do_close unlocks the mutex */
	}

	/*
	 *	Copied from src/lib/radius.c, rad_recv();
	 */
	if (fr_debug_flag) {
		char host_ipaddr[128];

		if ((packet->code > 0) && (packet->code < FR_MAX_PACKET_CODE)) {
			RDEBUG("tls_recv: %s packet from host %s port %d, id=%d, length=%d",
			       fr_packet_codes[packet->code],
			       inet_ntop(packet->src_ipaddr.af,
					 &packet->src_ipaddr.ipaddr,
					 host_ipaddr, sizeof(host_ipaddr)),
			       packet->src_port,
			       packet->id, (int) packet->data_len);
		} else {
			RDEBUG("tls_recv: Packet from host %s port %d code=%d, id=%d, length=%d",
			       inet_ntop(packet->src_ipaddr.af,
					 &packet->src_ipaddr.ipaddr,
					 host_ipaddr, sizeof(host_ipaddr)),
			       packet->src_port,
			       packet->code,
			       packet->id, (int) packet->data_len);
		}
	}

	FR_STATS_INC(auth, total_requests);

	return 1;
}
コード例 #20
0
ファイル: clidfs.c プロジェクト: ekohl/samba
NTSTATUS cli_dfs_get_referral(TALLOC_CTX *ctx,
			struct cli_state *cli,
			const char *path,
			struct client_dfs_referral **refs,
			size_t *num_refs,
			size_t *consumed)
{
	unsigned int data_len = 0;
	unsigned int param_len = 0;
	uint16_t setup[1];
	uint16_t recv_flags2;
	uint8_t *param = NULL;
	uint8_t *rdata = NULL;
	char *p;
	char *endp;
	smb_ucs2_t *path_ucs;
	char *consumed_path = NULL;
	uint16_t consumed_ucs;
	uint16 num_referrals;
	struct client_dfs_referral *referrals = NULL;
	NTSTATUS status;
	TALLOC_CTX *frame = talloc_stackframe();

	*num_refs = 0;
	*refs = NULL;

	SSVAL(setup, 0, TRANSACT2_GET_DFS_REFERRAL);

	param = talloc_array(talloc_tos(), uint8_t, 2);
	if (!param) {
		status = NT_STATUS_NO_MEMORY;
		goto out;
	}
	SSVAL(param, 0, 0x03);	/* max referral level */

	param = trans2_bytes_push_str(param, cli_ucs2(cli),
				      path, strlen(path)+1,
				      NULL);
	if (!param) {
		status = NT_STATUS_NO_MEMORY;
		goto out;
	}
	param_len = talloc_get_size(param);
	path_ucs = (smb_ucs2_t *)&param[2];

	status = cli_trans(talloc_tos(), cli, SMBtrans2,
			   NULL, 0xffff, 0, 0,
			   setup, 1, 0,
			   param, param_len, 2,
			   NULL, 0, CLI_BUFFER_SIZE,
			   &recv_flags2,
			   NULL, 0, NULL, /* rsetup */
			   NULL, 0, NULL,
			   &rdata, 4, &data_len);
	if (!NT_STATUS_IS_OK(status)) {
		goto out;
	}

	endp = (char *)rdata + data_len;

	consumed_ucs  = SVAL(rdata, 0);
	num_referrals = SVAL(rdata, 2);

	/* consumed_ucs is the number of bytes
	 * of the UCS2 path consumed not counting any
	 * terminating null. We need to convert
	 * back to unix charset and count again
	 * to get the number of bytes consumed from
	 * the incoming path. */

	errno = 0;
	if (pull_string_talloc(talloc_tos(),
			NULL,
			0,
			&consumed_path,
			path_ucs,
			consumed_ucs,
			STR_UNICODE) == 0) {
		if (errno != 0) {
			status = map_nt_error_from_unix(errno);
		} else {
			status = NT_STATUS_INVALID_NETWORK_RESPONSE;
		}
		goto out;
	}
	if (consumed_path == NULL) {
		status = map_nt_error_from_unix(errno);
		goto out;
	}
	*consumed = strlen(consumed_path);

	if (num_referrals != 0) {
		uint16 ref_version;
		uint16 ref_size;
		int i;
		uint16 node_offset;

		referrals = talloc_array(ctx, struct client_dfs_referral,
					 num_referrals);

		if (!referrals) {
			status = NT_STATUS_NO_MEMORY;
			goto out;
		}
		/* start at the referrals array */

		p = (char *)rdata+8;
		for (i=0; i<num_referrals && p < endp; i++) {
			if (p + 18 > endp) {
				goto out;
			}
			ref_version = SVAL(p, 0);
			ref_size    = SVAL(p, 2);
			node_offset = SVAL(p, 16);

			if (ref_version != 3) {
				p += ref_size;
				continue;
			}

			referrals[i].proximity = SVAL(p, 8);
			referrals[i].ttl       = SVAL(p, 10);

			if (p + node_offset > endp) {
				status = NT_STATUS_INVALID_NETWORK_RESPONSE;
				goto out;
			}
			clistr_pull_talloc(referrals,
					   (const char *)rdata,
					   recv_flags2,
					   &referrals[i].dfspath,
					   p+node_offset,
					   PTR_DIFF(endp, p+node_offset),
					   STR_TERMINATE|STR_UNICODE);

			if (!referrals[i].dfspath) {
				status = map_nt_error_from_unix(errno);
				goto out;
			}
			p += ref_size;
		}
		if (i < num_referrals) {
			status = NT_STATUS_INVALID_NETWORK_RESPONSE;
			goto out;
		}
	}
コード例 #21
0
ファイル: oxcfold.c プロジェクト: ThHirsch/openchange
_PUBLIC_ enum MAPISTATUS EcDoRpc_RopMoveCopyMessages(TALLOC_CTX *mem_ctx,
						     struct emsmdbp_context *emsmdbp_ctx,
						     struct EcDoRpc_MAPI_REQ *mapi_req,
						     struct EcDoRpc_MAPI_REPL *mapi_repl,
						     uint32_t *handles, uint16_t *size)
{
	enum MAPISTATUS		retval;
	uint32_t		handle;
	uint32_t                contextID;
	struct mapi_handles	*rec = NULL;
	void			*private_data = NULL;
	struct emsmdbp_object	*destination_object;
	struct emsmdbp_object   *source_object;
	uint64_t                *targetMIDs;
        uint32_t                i;
	bool			mapistore = false;

	OC_DEBUG(4, "exchange_emsmdb: [OXCFOLD] RopMoveCopyMessages (0x33)\n");

	/* Sanity checks */
	OPENCHANGE_RETVAL_IF(!emsmdbp_ctx, MAPI_E_NOT_INITIALIZED, NULL);
	OPENCHANGE_RETVAL_IF(!mapi_req, MAPI_E_INVALID_PARAMETER, NULL);
	OPENCHANGE_RETVAL_IF(!mapi_repl, MAPI_E_INVALID_PARAMETER, NULL);
	OPENCHANGE_RETVAL_IF(!handles, MAPI_E_INVALID_PARAMETER, NULL);
	OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL);

	mapi_repl->opnum = mapi_req->opnum;
	mapi_repl->error_code = MAPI_E_SUCCESS;
	mapi_repl->handle_idx = mapi_req->handle_idx;

	mapi_repl->u.mapi_MoveCopyMessages.PartialCompletion = 0;

	/* Get the destionation information */
	handle = handles[mapi_req->u.mapi_MoveCopyMessages.handle_idx];
	retval = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &rec);
	if (retval) {
		mapi_repl->error_code = MAPI_E_INVALID_OBJECT;
		OC_DEBUG(5, "  handle (%x) not found: %x\n", handle, mapi_req->handle_idx);
		goto end;
	}

	retval = mapi_handles_get_private_data(rec, &private_data);

	/* object is our destination folder */
        destination_object = private_data;
	if (!destination_object) {
		mapi_repl->error_code = MAPI_E_INVALID_OBJECT;
		OC_DEBUG(5, "  object (%x) not found: %x\n", handle, mapi_req->handle_idx);
		goto end;
	}
	
	/* Get the source folder information */
	handle = handles[mapi_req->handle_idx];
	retval = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &rec);
	if (retval) {
		mapi_repl->error_code = MAPI_E_INVALID_OBJECT;
		OC_DEBUG(5, "  handle (%x) not found: %x\n", handle, mapi_req->handle_idx);
		goto end;
	}

	retval = mapi_handles_get_private_data(rec, &private_data);
        source_object = private_data;
	if (!source_object) {
		mapi_repl->error_code = MAPI_E_INVALID_OBJECT;
		OC_DEBUG(5, "  object (%x) not found: %x\n", handle, mapi_req->u.mapi_MoveCopyMessages.handle_idx);
		goto end;
	}

	contextID = emsmdbp_get_contextID(destination_object);
	mapistore = emsmdbp_is_mapistore(source_object);
	if (mapistore) {
		/* We prepare a set of new MIDs for the backend */
		targetMIDs = talloc_array(NULL, uint64_t, mapi_req->u.mapi_MoveCopyMessages.count);
		for (i = 0; i < mapi_req->u.mapi_MoveCopyMessages.count; i++) {
			mapistore_indexing_get_new_folderID(emsmdbp_ctx->mstore_ctx, &targetMIDs[i]);
		}

		/* We invoke the backend method */
		mapistore_folder_move_copy_messages(emsmdbp_ctx->mstore_ctx, contextID, destination_object->backend_object, source_object->backend_object, mem_ctx, mapi_req->u.mapi_MoveCopyMessages.count, mapi_req->u.mapi_MoveCopyMessages.message_id, targetMIDs, NULL, NULL, mapi_req->u.mapi_MoveCopyMessages.WantCopy);
		talloc_free(targetMIDs);

		/* /\* The backend might do this for us. In any case, we try to add it ourselves *\/ */
		/* mapistore_indexing_record_add_mid(emsmdbp_ctx->mstore_ctx, contextID, targetMID); */
	}
	else {
		OC_DEBUG(0, "mapistore support not implemented yet - shouldn't occur\n");
		mapi_repl->error_code = MAPI_E_NO_SUPPORT;
	}

end:
	*size += libmapiserver_RopMoveCopyMessages_size(mapi_repl);

	return MAPI_E_SUCCESS;
}
コード例 #22
0
ファイル: smb2_negprot.c プロジェクト: aixoss/samba
NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
{
	struct smbXsrv_connection *xconn = req->xconn;
	NTSTATUS status;
	const uint8_t *inbody;
	const uint8_t *indyn = NULL;
	DATA_BLOB outbody;
	DATA_BLOB outdyn;
	DATA_BLOB negprot_spnego_blob;
	uint16_t security_offset;
	DATA_BLOB security_buffer;
	size_t expected_dyn_size = 0;
	size_t c;
	uint16_t security_mode;
	uint16_t dialect_count;
	uint16_t in_security_mode;
	uint32_t in_capabilities;
	DATA_BLOB in_guid_blob;
	struct GUID in_guid;
	struct smb2_negotiate_contexts in_c = { .num_contexts = 0, };
	struct smb2_negotiate_context *in_preauth = NULL;
	struct smb2_negotiate_context *in_cipher = NULL;
	struct smb2_negotiate_contexts out_c = { .num_contexts = 0, };
	DATA_BLOB out_negotiate_context_blob = data_blob_null;
	uint32_t out_negotiate_context_offset = 0;
	uint16_t out_negotiate_context_count = 0;
	uint16_t dialect = 0;
	uint32_t capabilities;
	DATA_BLOB out_guid_blob;
	struct GUID out_guid;
	enum protocol_types protocol = PROTOCOL_NONE;
	uint32_t max_limit;
	uint32_t max_trans = lp_smb2_max_trans();
	uint32_t max_read = lp_smb2_max_read();
	uint32_t max_write = lp_smb2_max_write();
	NTTIME now = timeval_to_nttime(&req->request_time);
	bool signing_required = true;
	bool ok;

	status = smbd_smb2_request_verify_sizes(req, 0x24);
	if (!NT_STATUS_IS_OK(status)) {
		return smbd_smb2_request_error(req, status);
	}
	inbody = SMBD_SMB2_IN_BODY_PTR(req);

	dialect_count = SVAL(inbody, 0x02);

	in_security_mode = SVAL(inbody, 0x04);
	in_capabilities = IVAL(inbody, 0x08);
	in_guid_blob = data_blob_const(inbody + 0x0C, 16);

	if (dialect_count == 0) {
		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
	}

	status = GUID_from_ndr_blob(&in_guid_blob, &in_guid);
	if (!NT_STATUS_IS_OK(status)) {
		return smbd_smb2_request_error(req, status);
	}

	expected_dyn_size = dialect_count * 2;
	if (SMBD_SMB2_IN_DYN_LEN(req) < expected_dyn_size) {
		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
	}
	indyn = SMBD_SMB2_IN_DYN_PTR(req);

	protocol = smbd_smb2_protocol_dialect_match(indyn,
					dialect_count,
					&dialect);

	for (c=0; protocol == PROTOCOL_NONE && c < dialect_count; c++) {
		if (lp_server_max_protocol() < PROTOCOL_SMB2_10) {
			break;
		}

		dialect = SVAL(indyn, c*2);
		if (dialect == SMB2_DIALECT_REVISION_2FF) {
			if (xconn->smb2.allow_2ff) {
				xconn->smb2.allow_2ff = false;
				protocol = PROTOCOL_SMB2_10;
				break;
			}
		}
	}

	if (protocol == PROTOCOL_NONE) {
		return smbd_smb2_request_error(req, NT_STATUS_NOT_SUPPORTED);
	}

	if (protocol >= PROTOCOL_SMB3_10) {
		uint32_t in_negotiate_context_offset = 0;
		uint16_t in_negotiate_context_count = 0;
		DATA_BLOB in_negotiate_context_blob = data_blob_null;
		size_t ofs;

		in_negotiate_context_offset = IVAL(inbody, 0x1C);
		in_negotiate_context_count = SVAL(inbody, 0x20);

		ofs = SMB2_HDR_BODY;
		ofs += SMBD_SMB2_IN_BODY_LEN(req);
		ofs += expected_dyn_size;
		if ((ofs % 8) != 0) {
			ofs += 8 - (ofs % 8);
		}

		if (in_negotiate_context_offset != ofs) {
			return smbd_smb2_request_error(req,
					NT_STATUS_INVALID_PARAMETER);
		}

		ofs -= SMB2_HDR_BODY;
		ofs -= SMBD_SMB2_IN_BODY_LEN(req);

		if (SMBD_SMB2_IN_DYN_LEN(req) < ofs) {
			return smbd_smb2_request_error(req,
					NT_STATUS_INVALID_PARAMETER);
		}

		in_negotiate_context_blob = data_blob_const(indyn,
						SMBD_SMB2_IN_DYN_LEN(req));

		in_negotiate_context_blob.data += ofs;
		in_negotiate_context_blob.length -= ofs;

		status = smb2_negotiate_context_parse(req,
					in_negotiate_context_blob, &in_c);
		if (!NT_STATUS_IS_OK(status)) {
			return smbd_smb2_request_error(req, status);
		}

		if (in_negotiate_context_count != in_c.num_contexts) {
			return smbd_smb2_request_error(req,
					NT_STATUS_INVALID_PARAMETER);
		}
	}

	if ((dialect != SMB2_DIALECT_REVISION_2FF) &&
	    (protocol >= PROTOCOL_SMB2_10) &&
	    !GUID_all_zero(&in_guid))
	{
		ok = remote_arch_cache_update(&in_guid);
		if (!ok) {
			return smbd_smb2_request_error(
				req, NT_STATUS_UNSUCCESSFUL);
		}
	}

	switch (get_remote_arch()) {
	case RA_VISTA:
	case RA_SAMBA:
	case RA_CIFSFS:
	case RA_OSX:
		break;
	default:
		set_remote_arch(RA_VISTA);
		break;
	}

	fstr_sprintf(remote_proto, "SMB%X_%02X",
		     (dialect >> 8) & 0xFF, dialect & 0xFF);

	reload_services(req->sconn, conn_snum_used, true);
	DEBUG(3,("Selected protocol %s\n", remote_proto));

	in_preauth = smb2_negotiate_context_find(&in_c,
					SMB2_PREAUTH_INTEGRITY_CAPABILITIES);
	if (protocol >= PROTOCOL_SMB3_10 && in_preauth == NULL) {
		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
	}
	in_cipher = smb2_negotiate_context_find(&in_c,
					SMB2_ENCRYPTION_CAPABILITIES);

	/* negprot_spnego() returns a the server guid in the first 16 bytes */
	negprot_spnego_blob = negprot_spnego(req, xconn);
	if (negprot_spnego_blob.data == NULL) {
		return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
	}

	if (negprot_spnego_blob.length < 16) {
		return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
	}

	security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
	/*
	 * We use xconn->smb1.signing_state as that's already present
	 * and used lpcfg_server_signing_allowed() to get the correct
	 * defaults, e.g. signing_required for an ad_dc.
	 */
	signing_required = smb_signing_is_mandatory(xconn->smb1.signing_state);
	if (signing_required) {
		security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED;
	}

	capabilities = 0;
	if (lp_host_msdfs()) {
		capabilities |= SMB2_CAP_DFS;
	}

	if (protocol >= PROTOCOL_SMB2_10 &&
	    lp_smb2_leases() &&
	    lp_oplocks(GLOBAL_SECTION_SNUM) &&
	    !lp_kernel_oplocks(GLOBAL_SECTION_SNUM))
	{
		capabilities |= SMB2_CAP_LEASING;
	}

	if ((protocol >= PROTOCOL_SMB2_24) &&
	    (lp_smb_encrypt(-1) != SMB_SIGNING_OFF) &&
	    (in_capabilities & SMB2_CAP_ENCRYPTION)) {
		capabilities |= SMB2_CAP_ENCRYPTION;
	}

	/*
	 * 0x10000 (65536) is the maximum allowed message size
	 * for SMB 2.0
	 */
	max_limit = 0x10000;

	if (protocol >= PROTOCOL_SMB2_10) {
		int p = 0;

		if (tsocket_address_is_inet(req->sconn->local_address, "ip")) {
			p = tsocket_address_inet_port(req->sconn->local_address);
		}

		/* largeMTU is not supported over NBT (tcp port 139) */
		if (p != NBT_SMB_PORT) {
			capabilities |= SMB2_CAP_LARGE_MTU;
			xconn->smb2.credits.multicredit = true;

			/*
			 * We allow up to almost 16MB.
			 *
			 * The maximum PDU size is 0xFFFFFF (16776960)
			 * and we need some space for the header.
			 */
			max_limit = 0xFFFF00;
		}
	}

	/*
	 * the defaults are 8MB, but we'll limit this to max_limit based on
	 * the dialect (64kb for SMB 2.0, 8MB for SMB >= 2.1 with LargeMTU)
	 *
	 * user configured values exceeding the limits will be overwritten,
	 * only smaller values will be accepted
	 */

	max_trans = MIN(max_limit, lp_smb2_max_trans());
	max_read = MIN(max_limit, lp_smb2_max_read());
	max_write = MIN(max_limit, lp_smb2_max_write());

	if (in_preauth != NULL) {
		size_t needed = 4;
		uint16_t hash_count;
		uint16_t salt_length;
		uint16_t selected_preauth = 0;
		const uint8_t *p;
		uint8_t buf[38];
		DATA_BLOB b;
		size_t i;

		if (in_preauth->data.length < needed) {
			return smbd_smb2_request_error(req,
					NT_STATUS_INVALID_PARAMETER);
		}

		hash_count = SVAL(in_preauth->data.data, 0);
		salt_length = SVAL(in_preauth->data.data, 2);

		if (hash_count == 0) {
			return smbd_smb2_request_error(req,
					NT_STATUS_INVALID_PARAMETER);
		}

		p = in_preauth->data.data + needed;
		needed += hash_count * 2;
		needed += salt_length;

		if (in_preauth->data.length < needed) {
			return smbd_smb2_request_error(req,
					NT_STATUS_INVALID_PARAMETER);
		}

		for (i=0; i < hash_count; i++) {
			uint16_t v;

			v = SVAL(p, 0);
			p += 2;

			if (v == SMB2_PREAUTH_INTEGRITY_SHA512) {
				selected_preauth = v;
				break;
			}
		}

		if (selected_preauth == 0) {
			return smbd_smb2_request_error(req,
				NT_STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP);
		}

		SSVAL(buf, 0,  1); /* HashAlgorithmCount */
		SSVAL(buf, 2, 32); /* SaltLength */
		SSVAL(buf, 4, selected_preauth);
		generate_random_buffer(buf + 6, 32);

		b = data_blob_const(buf, sizeof(buf));
		status = smb2_negotiate_context_add(req, &out_c,
					SMB2_PREAUTH_INTEGRITY_CAPABILITIES, b);
		if (!NT_STATUS_IS_OK(status)) {
			return smbd_smb2_request_error(req, status);
		}

		req->preauth = &req->xconn->smb2.preauth;
	}

	if (in_cipher != NULL) {
		size_t needed = 2;
		uint16_t cipher_count;
		const uint8_t *p;
		uint8_t buf[4];
		DATA_BLOB b;
		size_t i;
		bool aes_128_ccm_supported = false;
		bool aes_128_gcm_supported = false;

		capabilities &= ~SMB2_CAP_ENCRYPTION;

		if (in_cipher->data.length < needed) {
			return smbd_smb2_request_error(req,
					NT_STATUS_INVALID_PARAMETER);
		}

		cipher_count = SVAL(in_cipher->data.data, 0);

		if (cipher_count == 0) {
			return smbd_smb2_request_error(req,
					NT_STATUS_INVALID_PARAMETER);
		}

		p = in_cipher->data.data + needed;
		needed += cipher_count * 2;

		if (in_cipher->data.length < needed) {
			return smbd_smb2_request_error(req,
					NT_STATUS_INVALID_PARAMETER);
		}

		for (i=0; i < cipher_count; i++) {
			uint16_t v;

			v = SVAL(p, 0);
			p += 2;

			if (v == SMB2_ENCRYPTION_AES128_GCM) {
				aes_128_gcm_supported = true;
			}
			if (v == SMB2_ENCRYPTION_AES128_CCM) {
				aes_128_ccm_supported = true;
			}
		}

		/*
		 * For now we preferr CCM because our implementation
		 * is faster than GCM, see bug #11451.
		 */
		if (aes_128_ccm_supported) {
			xconn->smb2.server.cipher = SMB2_ENCRYPTION_AES128_CCM;
		} else if (aes_128_gcm_supported) {
			xconn->smb2.server.cipher = SMB2_ENCRYPTION_AES128_GCM;
		}

		SSVAL(buf, 0, 1); /* ChiperCount */
		SSVAL(buf, 2, xconn->smb2.server.cipher);

		b = data_blob_const(buf, sizeof(buf));
		status = smb2_negotiate_context_add(req, &out_c,
					SMB2_ENCRYPTION_CAPABILITIES, b);
		if (!NT_STATUS_IS_OK(status)) {
			return smbd_smb2_request_error(req, status);
		}
	}

	if (capabilities & SMB2_CAP_ENCRYPTION) {
		xconn->smb2.server.cipher = SMB2_ENCRYPTION_AES128_CCM;
	}

	if (protocol >= PROTOCOL_SMB2_22 &&
	    xconn->client->server_multi_channel_enabled)
	{
		if (in_capabilities & SMB2_CAP_MULTI_CHANNEL) {
			capabilities |= SMB2_CAP_MULTI_CHANNEL;
		}
	}

	security_offset = SMB2_HDR_BODY + 0x40;

#if 1
	/* Try SPNEGO auth... */
	security_buffer = data_blob_const(negprot_spnego_blob.data + 16,
					  negprot_spnego_blob.length - 16);
#else
	/* for now we want raw NTLMSSP */
	security_buffer = data_blob_const(NULL, 0);
#endif

	if (out_c.num_contexts != 0) {
		status = smb2_negotiate_context_push(req,
						&out_negotiate_context_blob,
						out_c);
		if (!NT_STATUS_IS_OK(status)) {
			return smbd_smb2_request_error(req, status);
		}
	}

	if (out_negotiate_context_blob.length != 0) {
		static const uint8_t zeros[8];
		size_t pad = 0;
		size_t ofs;

		outdyn = data_blob_dup_talloc(req, security_buffer);
		if (outdyn.length != security_buffer.length) {
			return smbd_smb2_request_error(req,
						NT_STATUS_NO_MEMORY);
		}

		ofs = security_offset + security_buffer.length;
		if ((ofs % 8) != 0) {
			pad = 8 - (ofs % 8);
		}
		ofs += pad;

		ok = data_blob_append(req, &outdyn, zeros, pad);
		if (!ok) {
			return smbd_smb2_request_error(req,
						NT_STATUS_NO_MEMORY);
		}

		ok = data_blob_append(req, &outdyn,
				      out_negotiate_context_blob.data,
				      out_negotiate_context_blob.length);
		if (!ok) {
			return smbd_smb2_request_error(req,
						NT_STATUS_NO_MEMORY);
		}

		out_negotiate_context_offset = ofs;
		out_negotiate_context_count = out_c.num_contexts;
	} else {
		outdyn = security_buffer;
	}

	out_guid_blob = data_blob_const(negprot_spnego_blob.data, 16);
	status = GUID_from_ndr_blob(&out_guid_blob, &out_guid);
	if (!NT_STATUS_IS_OK(status)) {
		return smbd_smb2_request_error(req, status);
	}

	outbody = smbd_smb2_generate_outbody(req, 0x40);
	if (outbody.data == NULL) {
		return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
	}

	SSVAL(outbody.data, 0x00, 0x40 + 1);	/* struct size */
	SSVAL(outbody.data, 0x02,
	      security_mode);			/* security mode */
	SSVAL(outbody.data, 0x04, dialect);	/* dialect revision */
	SSVAL(outbody.data, 0x06,
	      out_negotiate_context_count);	/* reserved/NegotiateContextCount */
	memcpy(outbody.data + 0x08,
	       out_guid_blob.data, 16);	/* server guid */
	SIVAL(outbody.data, 0x18,
	      capabilities);			/* capabilities */
	SIVAL(outbody.data, 0x1C, max_trans);	/* max transact size */
	SIVAL(outbody.data, 0x20, max_read);	/* max read size */
	SIVAL(outbody.data, 0x24, max_write);	/* max write size */
	SBVAL(outbody.data, 0x28, now);		/* system time */
	SBVAL(outbody.data, 0x30, 0);		/* server start time */
	SSVAL(outbody.data, 0x38,
	      security_offset);			/* security buffer offset */
	SSVAL(outbody.data, 0x3A,
	      security_buffer.length);		/* security buffer length */
	SIVAL(outbody.data, 0x3C,
	      out_negotiate_context_offset);	/* reserved/NegotiateContextOffset */

	req->sconn->using_smb2 = true;

	if (dialect != SMB2_DIALECT_REVISION_2FF) {
		struct smbXsrv_client_global0 *global0 = NULL;

		status = smbXsrv_connection_init_tables(xconn, protocol);
		if (!NT_STATUS_IS_OK(status)) {
			return smbd_smb2_request_error(req, status);
		}

		xconn->smb2.client.capabilities = in_capabilities;
		xconn->smb2.client.security_mode = in_security_mode;
		xconn->smb2.client.guid = in_guid;
		xconn->smb2.client.num_dialects = dialect_count;
		xconn->smb2.client.dialects = talloc_array(xconn,
							   uint16_t,
							   dialect_count);
		if (xconn->smb2.client.dialects == NULL) {
			return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
		}
		for (c=0; c < dialect_count; c++) {
			xconn->smb2.client.dialects[c] = SVAL(indyn, c*2);
		}

		xconn->smb2.server.capabilities = capabilities;
		xconn->smb2.server.security_mode = security_mode;
		xconn->smb2.server.guid = out_guid;
		xconn->smb2.server.dialect = dialect;
		xconn->smb2.server.max_trans = max_trans;
		xconn->smb2.server.max_read  = max_read;
		xconn->smb2.server.max_write = max_write;

		if (xconn->protocol < PROTOCOL_SMB2_10) {
			/*
			 * SMB2_02 doesn't support client guids
			 */
			return smbd_smb2_request_done(req, outbody, &outdyn);
		}

		if (!xconn->client->server_multi_channel_enabled) {
			/*
			 * Only deal with the client guid database
			 * if multi-channel is enabled.
			 */
			return smbd_smb2_request_done(req, outbody, &outdyn);
		}

		if (xconn->smb2.client.guid_verified) {
			/*
			 * The connection was passed from another
			 * smbd process.
			 */
			return smbd_smb2_request_done(req, outbody, &outdyn);
		}

		status = smb2srv_client_lookup_global(xconn->client,
						xconn->smb2.client.guid,
						req, &global0);
		/*
		 * TODO: check for races...
		 */
		if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECTID_NOT_FOUND)) {
			/*
			 * This stores the new client information in
			 * smbXsrv_client_global.tdb
			 */
			xconn->client->global->client_guid =
						xconn->smb2.client.guid;
			status = smbXsrv_client_update(xconn->client);
			if (!NT_STATUS_IS_OK(status)) {
				return status;
			}

			xconn->smb2.client.guid_verified = true;
		} else if (NT_STATUS_IS_OK(status)) {
			status = smb2srv_client_connection_pass(req,
								global0);
			if (!NT_STATUS_IS_OK(status)) {
				return smbd_smb2_request_error(req, status);
			}

			smbd_server_connection_terminate(xconn,
							 "passed connection");
			return NT_STATUS_OBJECTID_EXISTS;
		} else {
			return smbd_smb2_request_error(req, status);
		}
	}

	return smbd_smb2_request_done(req, outbody, &outdyn);
}
コード例 #23
0
ファイル: eap_tls.c プロジェクト: mommel/freeradius-server
/*
 * EAPTLS_PACKET
 * code   =  EAP-code
 * id     =  EAP-id
 * length = code + id + length + flags + tlsdata
 *	=  1   +  1 +   2    +  1    +  X
 * length = EAP-length - 1(EAP-Type = 1 octet)
 * flags  = EAP-typedata[0] (1 octet)
 * dlen   = EAP-typedata[1-4] (4 octets), if L flag set
 *	= length - 5(code+id+length+flags), otherwise
 * data   = EAP-typedata[5-n], if L flag set
 *	= EAP-typedata[1-n], otherwise
 * packet = EAP-typedata (complete typedata)
 *
 * Points to consider during EAP-TLS data extraction
 * 1. In the received packet, No data will be present incase of ACK-NAK
 * 2. Incase if more fragments need to be received then ACK after retreiving this fragment.
 *
 *  RFC 2716 Section 4.2.  PPP EAP TLS Request Packet
 *
 *  0		   1		   2		   3
 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *  |     Code      |   Identifier  |	    Length	     |
 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *  |     Type      |     Flags     |      TLS Message Length
 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *  |     TLS Message Length	|       TLS Data...
 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *
 *  The Length field is two octets and indicates the length of the EAP
 *  packet including the Code, Identifir, Length, Type, and TLS data
 *  fields.
 */
static EAPTLS_PACKET *eaptls_extract(REQUEST *request, EAP_DS *eap_ds, fr_tls_status_t status)
{
	EAPTLS_PACKET	*tlspacket;
	uint32_t	data_len = 0;
	uint32_t	len = 0;
	uint8_t		*data = NULL;

	if (status  == FR_TLS_INVALID)
		return NULL;

	/*
	 *	The main EAP code & eaptls_verify() take care of
	 *	ensuring that the packet is OK, and that we can
	 *	extract the various fields we want.
	 *
	 *	e.g. a TLS packet with zero data is allowed as an ACK,
	 *	but we will never see it here, as we will simply
	 *	send another fragment, instead of trying to extract
	 *	the data.
	 *
	 *	MUST have TLS type octet, followed by flags, followed
	 *	by data.
	 */
	assert(eap_ds->response->length > 2);

	tlspacket = talloc(eap_ds, EAPTLS_PACKET);
	if (!tlspacket) return NULL;

	/*
	 *	Code & id for EAPTLS & EAP are same
	 *	but eaptls_length = eap_length - 1(EAP-Type = 1 octet)
	 *
	 *	length = code + id + length + type + tlsdata
	 *	       =  1   +  1 +   2    +  1    +  X
	 */
	tlspacket->code = eap_ds->response->code;
	tlspacket->id = eap_ds->response->id;
	tlspacket->length = eap_ds->response->length - 1; /* EAP type */
	tlspacket->flags = eap_ds->response->type.data[0];

	/*
	 *	A quick sanity check of the flags.  If we've been told
	 *	that there's a length, and there isn't one, then stop.
	 */
	if (TLS_LENGTH_INCLUDED(tlspacket->flags) &&
	    (tlspacket->length < 5)) { /* flags + TLS message length */
		RDEBUG("Invalid EAP-TLS packet received.  (Length bit is set, but no length was found.)");
		talloc_free(tlspacket);
		return NULL;
	}

	/*
	 *	If the final TLS packet is larger than we can handle, die
	 *	now.
	 *
	 *	Likewise, if the EAP packet says N bytes, and the TLS
	 *	packet says there's fewer bytes, it's a problem.
	 *
	 *	FIXME: Try to ensure that the claimed length is
	 *	consistent across multiple TLS fragments.
	 */
	if (TLS_LENGTH_INCLUDED(tlspacket->flags)) {
		memcpy(&data_len, &eap_ds->response->type.data[1], 4);
		data_len = ntohl(data_len);
		if (data_len > MAX_RECORD_SIZE) {
			RDEBUG("The EAP-TLS packet will contain more data than we can process");
			talloc_free(tlspacket);
			return NULL;
		}

#if 0
		DEBUG2(" TLS: %d %d\n", data_len, tlspacket->length);

		if (data_len < tlspacket->length) {
			RDEBUG("EAP-TLS packet claims to be smaller than the encapsulating EAP packet");
			talloc_free(tlspacket);
			return NULL;
		}
#endif
	}

	switch (status) {
	/*
	 *	The TLS Message Length field is four octets, and
	 *	provides the total length of the TLS message or set of
	 *	messages that is being fragmented; this simplifies
	 *	buffer allocation.
	 *
	 *	Dynamic allocation of buffers as & when we know the
	 *	length should solve the problem.
	 */
	case FR_TLS_FIRST_FRAGMENT:
	case FR_TLS_LENGTH_INCLUDED:
	case FR_TLS_MORE_FRAGMENTS_WITH_LENGTH:
		if (tlspacket->length < 5) { /* flags + TLS message length */
			RDEBUG("Invalid EAP-TLS packet received.  (Expected length, got none.)");
			talloc_free(tlspacket);
			return NULL;
		}

		/*
		 *	Extract all the TLS fragments from the
		 *	previous eap_ds Start appending this
		 *	fragment to the above ds
		 */
		memcpy(&data_len, &eap_ds->response->type.data[1], sizeof(uint32_t));
		data_len = ntohl(data_len);
		data = (eap_ds->response->type.data + 5/*flags+TLS-Length*/);
		len = eap_ds->response->type.length - 5/*flags+TLS-Length*/;

		/*
		 *	Hmm... this should be an error, too.
		 */
		if (data_len > len) {
			data_len = len;
		}
		break;

		/*
		 *	Data length is implicit, from the EAP header.
		 */
	case FR_TLS_MORE_FRAGMENTS:
	case FR_TLS_OK:
		data_len = eap_ds->response->type.length - 1/*flags*/;
		data = eap_ds->response->type.data + 1/*flags*/;
		break;

	default:
		RDEBUG("Invalid EAP-TLS packet received");
		talloc_free(tlspacket);
		return NULL;
	}

	tlspacket->dlen = data_len;
	if (data_len) {
		tlspacket->data = talloc_array(tlspacket, uint8_t,
					       data_len);
		if (!tlspacket->data) {
			talloc_free(tlspacket);
			return NULL;
		}
		memcpy(tlspacket->data, data, data_len);
	}

	return tlspacket;
}
コード例 #24
0
ファイル: rlm_eap_pwd.c プロジェクト: janetuk/freeradius
static int mod_process(void *arg, eap_handler_t *handler)
{
	pwd_session_t *session;
	pwd_hdr *hdr;
	pwd_id_packet_t *packet;
	eap_packet_t *response;
	REQUEST *request, *fake;
	VALUE_PAIR *pw, *vp;
	EAP_DS *eap_ds;
	size_t in_len;
	int ret = 0;
	eap_pwd_t *inst = (eap_pwd_t *)arg;
	uint16_t offset;
	uint8_t exch, *in, *ptr, msk[MSK_EMSK_LEN], emsk[MSK_EMSK_LEN];
	uint8_t peer_confirm[SHA256_DIGEST_LENGTH];

	if (((eap_ds = handler->eap_ds) == NULL) || !inst) return 0;

	session = (pwd_session_t *)handler->opaque;
	request = handler->request;
	response = handler->eap_ds->response;
	hdr = (pwd_hdr *)response->type.data;

	/*
	 *	The header must be at least one byte.
	 */
	if (!hdr || (response->type.length < sizeof(pwd_hdr))) {
		RDEBUG("Packet with insufficient data");
		return 0;
	}

	in = hdr->data;
	in_len = response->type.length - sizeof(pwd_hdr);

	/*
	* see if we're fragmenting, if so continue until we're done
	*/
	if (session->out_pos) {
		if (in_len) RDEBUG2("pwd got something more than an ACK for a fragment");

		return send_pwd_request(session, eap_ds);
	}

	/*
	* the first fragment will have a total length, make a
	* buffer to hold all the fragments
	*/
	if (EAP_PWD_GET_LENGTH_BIT(hdr)) {
		if (session->in) {
			RDEBUG2("pwd already alloced buffer for fragments");
			return 0;
		}

		if (in_len < 2) {
			RDEBUG("Invalid packet: length bit set, but no length field");
			return 0;
		}

		session->in_len = ntohs(in[0] * 256 | in[1]);
		if ((session->in = talloc_zero_array(session, uint8_t, session->in_len)) == NULL) {
			RDEBUG2("pwd cannot allocate %zd buffer to hold fragments",
				session->in_len);
			return 0;
		}
		memset(session->in, 0, session->in_len);
		session->in_pos = 0;
		in += sizeof(uint16_t);
		in_len -= sizeof(uint16_t);
	}

	/*
	 * all fragments, including the 1st will have the M(ore) bit set,
	 * buffer those fragments!
	 */
	if (EAP_PWD_GET_MORE_BIT(hdr)) {
		rad_assert(session->in != NULL);

		if ((session->in_pos + in_len) > session->in_len) {
			RDEBUG2("Fragment overflows packet.");
			return 0;
		}

		memcpy(session->in + session->in_pos, in, in_len);
		session->in_pos += in_len;

		/*
		 * send back an ACK for this fragment
		 */
		exch = EAP_PWD_GET_EXCHANGE(hdr);
		eap_ds->request->code = PW_EAP_REQUEST;
		eap_ds->request->type.num = PW_EAP_PWD;
		eap_ds->request->type.length = sizeof(pwd_hdr);
		if ((eap_ds->request->type.data = talloc_array(eap_ds->request, uint8_t, sizeof(pwd_hdr))) == NULL) {
			return 0;
		}
		hdr = (pwd_hdr *)eap_ds->request->type.data;
		EAP_PWD_SET_EXCHANGE(hdr, exch);
		return 1;
	}


	if (session->in) {
		/*
		 * the last fragment...
		 */
		if ((session->in_pos + in_len) > session->in_len) {
			RDEBUG2("pwd will not overflow a fragment buffer. Nope, not prudent");
			return 0;
		}
		memcpy(session->in + session->in_pos, in, in_len);
		in = session->in;
		in_len = session->in_len;
	}

	switch (session->state) {
	case PWD_STATE_ID_REQ:
	{
		BIGNUM	*x = NULL, *y = NULL;

		if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_ID) {
			RDEBUG2("pwd exchange is incorrect: not ID");
			return 0;
		}

		packet = (pwd_id_packet_t *) in;
		if (in_len < sizeof(*packet)) {
			RDEBUG("Packet is too small (%zd < %zd).", in_len, sizeof(*packet));
			return 0;
		}

		if ((packet->prf != EAP_PWD_DEF_PRF) ||
		    (packet->random_function != EAP_PWD_DEF_RAND_FUN) ||
		    (packet->prep != EAP_PWD_PREP_NONE) ||
		    (CRYPTO_memcmp(packet->token, &session->token, 4)) ||
		    (packet->group_num != ntohs(session->group_num))) {
			RDEBUG2("pwd id response is invalid");
			return 0;
		}
		/*
		 * we've agreed on the ciphersuite, record it...
		 */
		ptr = (uint8_t *)&session->ciphersuite;
		memcpy(ptr, (char *)&packet->group_num, sizeof(uint16_t));
		ptr += sizeof(uint16_t);
		*ptr = EAP_PWD_DEF_RAND_FUN;
		ptr += sizeof(uint8_t);
		*ptr = EAP_PWD_DEF_PRF;

		session->peer_id_len = in_len - sizeof(pwd_id_packet_t);
		if (session->peer_id_len >= sizeof(session->peer_id)) {
			RDEBUG2("pwd id response is malformed");
			return 0;
		}

		memcpy(session->peer_id, packet->identity, session->peer_id_len);
		session->peer_id[session->peer_id_len] = '\0';

		/*
		 * make fake request to get the password for the usable ID
		 */
		if ((fake = request_alloc_fake(handler->request)) == NULL) {
			RDEBUG("pwd unable to create fake request!");
			return 0;
		}
		fake->username = fr_pair_afrom_num(fake->packet, PW_USER_NAME, 0);
		if (!fake->username) {
			RDEBUG("Failed creating pair for peer id");
			talloc_free(fake);
			return 0;
		}
		fr_pair_value_bstrncpy(fake->username, session->peer_id, session->peer_id_len);
		fr_pair_add(&fake->packet->vps, fake->username);

		if ((vp = fr_pair_find_by_num(request->config, PW_VIRTUAL_SERVER, 0, TAG_ANY)) != NULL) {
			fake->server = vp->vp_strvalue;
		} else if (inst->virtual_server) {
			fake->server = inst->virtual_server;
		} /* else fake->server == request->server */

		RDEBUG("Sending tunneled request");
		rdebug_pair_list(L_DBG_LVL_1, request, fake->packet->vps, NULL);

		if (fake->server) {
			RDEBUG("server %s {", fake->server);
		} else {
			RDEBUG("server {");
		}

		/*
		 *	Call authorization recursively, which will
		 *	get the password.
		 */
		RINDENT();
		process_authorize(0, fake);
		REXDENT();

		/*
		 *	Note that we don't do *anything* with the reply
		 *	attributes.
		 */
		if (fake->server) {
			RDEBUG("} # server %s", fake->server);
		} else {
			RDEBUG("}");
		}

		RDEBUG("Got tunneled reply code %d", fake->reply->code);
		rdebug_pair_list(L_DBG_LVL_1, request, fake->reply->vps, NULL);

		if ((pw = fr_pair_find_by_num(fake->config, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) == NULL) {
			DEBUG2("failed to find password for %s to do pwd authentication",
			session->peer_id);
			talloc_free(fake);
			return 0;
		}

		if (compute_password_element(session, session->group_num,
			     		     pw->data.strvalue, strlen(pw->data.strvalue),
					     inst->server_id, strlen(inst->server_id),
					     session->peer_id, strlen(session->peer_id),
					     &session->token)) {
			DEBUG2("failed to obtain password element");
			talloc_free(fake);
			return 0;
		}
		TALLOC_FREE(fake);

		/*
		 * compute our scalar and element
		 */
		if (compute_scalar_element(session, inst->bnctx)) {
			DEBUG2("failed to compute server's scalar and element");
			return 0;
		}

		MEM(x = BN_new());
		MEM(y = BN_new());

		/*
		 * element is a point, get both coordinates: x and y
		 */
		if (!EC_POINT_get_affine_coordinates_GFp(session->group, session->my_element, x, y,
							 inst->bnctx)) {
			DEBUG2("server point assignment failed");
			BN_clear_free(x);
			BN_clear_free(y);
			return 0;
		}

		/*
		 * construct request
		 */
		session->out_len = BN_num_bytes(session->order) + (2 * BN_num_bytes(session->prime));
		if ((session->out = talloc_array(session, uint8_t, session->out_len)) == NULL) {
			return 0;
		}
		memset(session->out, 0, session->out_len);

		ptr = session->out;
		offset = BN_num_bytes(session->prime) - BN_num_bytes(x);
		BN_bn2bin(x, ptr + offset);
		BN_clear_free(x);

		ptr += BN_num_bytes(session->prime);
		offset = BN_num_bytes(session->prime) - BN_num_bytes(y);
		BN_bn2bin(y, ptr + offset);
		BN_clear_free(y);

		ptr += BN_num_bytes(session->prime);
		offset = BN_num_bytes(session->order) - BN_num_bytes(session->my_scalar);
		BN_bn2bin(session->my_scalar, ptr + offset);

		session->state = PWD_STATE_COMMIT;
		ret = send_pwd_request(session, eap_ds);
	}
		break;

		case PWD_STATE_COMMIT:
		if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_COMMIT) {
			RDEBUG2("pwd exchange is incorrect: not commit!");
			return 0;
		}

		/*
		 * process the peer's commit and generate the shared key, k
		 */
		if (process_peer_commit(session, in, in_len, inst->bnctx)) {
			RDEBUG2("failed to process peer's commit");
			return 0;
		}

		/*
		 * compute our confirm blob
		 */
		if (compute_server_confirm(session, session->my_confirm, inst->bnctx)) {
			ERROR("rlm_eap_pwd: failed to compute confirm!");
			return 0;
		}

		/*
		 * construct a response...which is just our confirm blob
		 */
		session->out_len = SHA256_DIGEST_LENGTH;
		if ((session->out = talloc_array(session, uint8_t, session->out_len)) == NULL) {
			return 0;
		}

		memset(session->out, 0, session->out_len);
		memcpy(session->out, session->my_confirm, SHA256_DIGEST_LENGTH);

		session->state = PWD_STATE_CONFIRM;
		ret = send_pwd_request(session, eap_ds);
		break;

	case PWD_STATE_CONFIRM:
		if (in_len < SHA256_DIGEST_LENGTH) {
			RDEBUG("Peer confirm is too short (%zd < %d)",
			       in_len, SHA256_DIGEST_LENGTH);
			return 0;
		}

		if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_CONFIRM) {
			RDEBUG2("pwd exchange is incorrect: not commit!");
			return 0;
		}
		if (compute_peer_confirm(session, peer_confirm, inst->bnctx)) {
			RDEBUG2("pwd exchange cannot compute peer's confirm");
			return 0;
		}
		if (CRYPTO_memcmp(peer_confirm, in, SHA256_DIGEST_LENGTH)) {
			RDEBUG2("pwd exchange fails: peer confirm is incorrect!");
			return 0;
		}
		if (compute_keys(session, peer_confirm, msk, emsk)) {
			RDEBUG2("pwd exchange cannot generate (E)MSK!");
			return 0;
		}
		eap_ds->request->code = PW_EAP_SUCCESS;
		/*
		 * return the MSK (in halves)
		 */
		eap_add_reply(handler->request, "MS-MPPE-Recv-Key", msk, MPPE_KEY_LEN);
		eap_add_reply(handler->request, "MS-MPPE-Send-Key", msk + MPPE_KEY_LEN, MPPE_KEY_LEN);

		ret = 1;
		break;

	default:
		RDEBUG2("unknown PWD state");
		return 0;
	}

	/*
	 * we processed the buffered fragments, get rid of them
	 */
	if (session->in) {
		talloc_free(session->in);
		session->in = NULL;
	}

	return ret;
}
コード例 #25
0
ファイル: cmd_eventlog.c プロジェクト: Alexandr-Galko/samba
static NTSTATUS cmd_eventlog_loginfo(struct rpc_pipe_client *cli,
				     TALLOC_CTX *mem_ctx,
				     int argc,
				     const char **argv)
{
	NTSTATUS status, result;
	struct policy_handle handle;
	uint8_t *buffer = NULL;
	uint32_t buf_size = 0;
	uint32_t bytes_needed = 0;
	struct dcerpc_binding_handle *b = cli->binding_handle;

	if (argc != 2) {
		printf("Usage: %s logname\n", argv[0]);
		return NT_STATUS_OK;
	}

	status = get_eventlog_handle(cli, mem_ctx, argv[1], &handle);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	status = dcerpc_eventlog_GetLogInformation(b, mem_ctx,
						   &handle,
						   0, /* level */
						   buffer,
						   buf_size,
						   &bytes_needed,
						   &result);
	if (!NT_STATUS_IS_OK(status)) {
		goto done;
	}
	if (!NT_STATUS_IS_OK(result) &&
	    !NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL)) {
		goto done;
	}

	buf_size = bytes_needed;
	buffer = talloc_array(mem_ctx, uint8_t, bytes_needed);
	if (!buffer) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	status = dcerpc_eventlog_GetLogInformation(b, mem_ctx,
						   &handle,
						   0, /* level */
						   buffer,
						   buf_size,
						   &bytes_needed,
						   &result);
	if (!NT_STATUS_IS_OK(status)) {
		goto done;
	}
	if (!NT_STATUS_IS_OK(result)) {
		status = result;
		goto done;
	}

 done:
	dcerpc_eventlog_CloseEventLog(b, mem_ctx, &handle, &result);

	return status;
}
コード例 #26
0
/** Authenticate a previously sent challenge
 *
 */
static int mod_process(void *instance, eap_handler_t *handler)
{
	uint8_t *in;
	uint8_t *out = NULL;

	uint8_t *ikemsg;
	u_int32_t len;

	uint8_t *sikemsg = NULL;   //out message
	u_int32_t slen = 0;

	u_int32_t olen = 0;
	struct ikev2_ctx *i2 = (struct ikev2_ctx*)instance;
	struct EAPHeader *hdr;

	struct IKEv2Data *ikev2_data;
	struct IKEv2Session *session;

	INFO(IKEv2_LOG_PREFIX "authenticate" );

	rad_assert(handler->request != NULL);
	rad_assert(handler->stage == PROCESS);

	EAP_DS *eap_ds=handler->eap_ds;
	if (!eap_ds ||
	    !eap_ds->response ||
	    (eap_ds->response->code != PW_IKEV2_RESPONSE) ||
	    eap_ds->response->type.num != PW_EAP_IKEV2 ||
	    !eap_ds->response->type.data) {
		ERROR(IKEv2_LOG_PREFIX "corrupted data");
		return -1;
	}

	in = talloc_array(eap_ds, uint8_t, eap_ds->response->length);
	if (in){
		ERROR(IKEv2_LOG_PREFIX "alloc error");
		return -1;
	}

	rad_assert(in != NULL);
	hdr = (struct EAPHeader *)in;

	hdr->Code = eap_ds->response->code;
	hdr->Id = eap_ds->response->id;
	hdr->Length = htons(eap_ds->response->length);
	hdr->Type = eap_ds->response->type.num;
	memcpy(in + 5, eap_ds->response->type.data, eap_ds->response->length - 5);

	ikev2_data = (struct IKEv2Data*)handler->opaque;
	session = ikev2_data->session;
	session->timestamp = time(NULL);

	if (!session->fragdata) session->sendfrag = false;

	if (session->sendfrag && !ParseFragmentAck(in, session)){
		session->eapMsgID = eap_ds->response->id + 1;

		olen = CreateIKEv2Message(i2, NULL, 0, false, hdr->Id, session, (uint8_t **)&out);
		talloc_free(in);

		if (compose_rad_message(out,olen,handler->eap_ds)) {
			free(out);
			return 0;
		}

		free(out);
		return 1;
	}

	session->eapMsgID = eap_ds->response->id + 1;

	if (ParseIKEv2Message(in, &ikemsg, &len, session)){
		if (ikemsg != NULL) free(ikemsg);

		handler->eap_ds->request->code=PW_EAP_FAILURE;
		INFO(IKEv2_LOG_PREFIX "Discarded packet");

		return 1;
	}

	/* Send fragment ack */
	if (!ikemsg || !len) {
		if (session->SK_ready) session->include_integ = 1;

		olen = CreateFragmentAck(in, &out, session); // confirm fragment
		TALLOC_FREE(in);

		if (compose_rad_message(out,olen,handler->eap_ds)) {
			free(out);
			return 0;
		}

		free(out);
		return 1;
	}
	TALLOC_FREE(in);

	if (IKEv2ProcessMsg(i2, ikemsg, &sikemsg, &slen, session) != IKEv2_RET_OK) {
		INFO(IKEv2_LOG_PREFIX "EAP_STATE_DISCARD");
		//session->State = EAP_STATE_DISCARD;
		free(out);
		return 1;
	}

	free(ikemsg);

	/* If there is there is something to send */
	if (slen != 0){
		olen = CreateIKEv2Message(i2, sikemsg, slen, false, 0, session, &out);
		if (session->fragdata) session->sendfrag = true;
	} else {
		if (session->Status == IKEv2_SST_FAILED ) {
			INFO(IKEv2_LOG_PREFIX "FAILED");
			olen = CreateResultMessage( false, session, &out );
		}

		if(session->Status == IKEv2_SST_ESTABLISHED) {
			INFO(IKEv2_LOG_PREFIX "SUCCESS");
			olen = CreateResultMessage(true, session, &out);
			session->fFastReconnect = i2->enableFastReconnect;

			GenEapKeys(session ,EAP_IKEv2_KEY_LEN);
			set_mppe_keys(handler);
		}

		// keep sessions in memory, only reference cleared
		ikev2_data->session = NULL;
	}
	if ((olen > 0) && (out != NULL)){
		if (compose_rad_message(out, olen, handler->eap_ds)){
			free(out);
			return 0;
		}
	}

	free(out);
	return 1;
}
コード例 #27
0
/** Send the challenge itself
 *
 * Challenges will come from one of three places eventually:
 *
 * 1  from attributes like PW_EAP_SIM_RANDx
 *	    (these might be retrived from a database)
 *
 * 2  from internally implemented SIM authenticators
 *	    (a simple one based upon XOR will be provided)
 *
 * 3  from some kind of SS7 interface.
 *
 * For now, they only come from attributes.
 * It might be that the best way to do 2/3 will be with a different
 * module to generate/calculate things.
 *
 */
static int eap_sim_sendchallenge(eap_handler_t *handler)
{
	REQUEST *request = handler->request;
	eap_sim_state_t *ess;
	VALUE_PAIR **invps, **outvps, *newvp;
	RADIUS_PACKET *packet;
	uint8_t *p;

	ess = (eap_sim_state_t *)handler->opaque;
	rad_assert(handler->request != NULL);
	rad_assert(handler->request->reply);

	/*
	 *	Invps is the data from the client but this is for non-protocol data here.
	 *	We should already have consumed any client originated data.
	 */
	invps = &handler->request->packet->vps;

	/*
	 *	Outvps is the data to the client
	 */
	packet = handler->request->reply;
	outvps = &packet->vps;

	if (RDEBUG_ENABLED2) {
		RDEBUG2("EAP-SIM decoded packet");
		rdebug_pair_list(L_DBG_LVL_2, request, *invps, NULL);
	}

	/*
	 *	Okay, we got the challenges! Put them into an attribute.
	 */
	newvp = paircreate(packet, PW_EAP_SIM_RAND, 0);
	newvp->length = 2 + (EAPSIM_RAND_SIZE * 3);
	newvp->vp_octets = p = talloc_array(newvp, uint8_t, newvp->length);

	memset(p, 0, 2); /* clear reserved bytes */
	p += 2;
	memcpy(p, ess->keys.rand[0], EAPSIM_RAND_SIZE);
	p += EAPSIM_RAND_SIZE;
	memcpy(p, ess->keys.rand[1], EAPSIM_RAND_SIZE);
	p += EAPSIM_RAND_SIZE;
	memcpy(p, ess->keys.rand[2], EAPSIM_RAND_SIZE);
	pairadd(outvps, newvp);

	/*
	 *	Set the EAP_ID - new value
	 */
	newvp = paircreate(packet, PW_EAP_ID, 0);
	newvp->vp_integer = ess->sim_id++;
	pairreplace(outvps, newvp);

	/*
	 *	Make a copy of the identity
	 */
	ess->keys.identitylen = strlen(handler->identity);
	memcpy(ess->keys.identity, handler->identity, ess->keys.identitylen);

	/*
	 *	Use the SIM identity, if available
	 */
	newvp = pairfind(*invps, PW_EAP_SIM_IDENTITY, 0, TAG_ANY);
	if (newvp && newvp->length > 2) {
		uint16_t len;

		memcpy(&len, newvp->vp_octets, sizeof(uint16_t));
		len = ntohs(len);
		if (len <= newvp->length - 2 && len <= MAX_STRING_LEN) {
			ess->keys.identitylen = len;
			memcpy(ess->keys.identity, newvp->vp_octets + 2, ess->keys.identitylen);
		}
	}

	/*
	 *	All set, calculate keys!
	 */
	eapsim_calculate_keys(&ess->keys);

#ifdef EAP_SIM_DEBUG_PRF
	eapsim_dump_mk(&ess->keys);
#endif

	/*
	 *	Need to include an AT_MAC attribute so that it will get
	 *	calculated. The NONCE_MT and the MAC are both 16 bytes, so
	 *	We store the NONCE_MT in the MAC for the encoder, which
	 *	will pull it out before it does the operation.
	 */
	newvp = paircreate(packet, PW_EAP_SIM_MAC, 0);
	pairmemcpy(newvp, ess->keys.nonce_mt, 16);
	pairreplace(outvps, newvp);

	newvp = paircreate(packet, PW_EAP_SIM_KEY, 0);
	pairmemcpy(newvp, ess->keys.K_aut, 16);
	pairreplace(outvps, newvp);

	/* the SUBTYPE, set to challenge. */
	newvp = paircreate(packet, PW_EAP_SIM_SUBTYPE, 0);
	newvp->vp_integer = EAPSIM_CHALLENGE;
	pairreplace(outvps, newvp);

	return 1;
}
コード例 #28
0
ファイル: IStoreFolder.c プロジェクト: EasyLinux/Openchange
/**
   \details Retrieve the message properties for an already open message.

   This function is very similar to OpenMessage, but works on an already
   open message object.

   \param obj_message the message object to retrieve the properties for.

   \return MAPI_E_SUCCESS on success, otherwise MAPI error.

   \note Developers may also call GetLastError() to retrieve the last
   MAPI error code. Possible MAPI error codes are:
   - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
   - MAPI_E_INVALID_PARAMETER: obj_store is undefined
   - MAPI_E_CALL_FAILED: A network problem was encountered during the
     transaction

   \sa OpenMessage
*/
_PUBLIC_ enum MAPISTATUS ReloadCachedInformation(mapi_object_t *obj_message)
{
	struct mapi_context			*mapi_ctx;
	struct mapi_request			*mapi_request;
	struct mapi_response			*mapi_response;
	struct EcDoRpc_MAPI_REQ			*mapi_req;
	struct ReloadCachedInformation_req	request;
	struct ReloadCachedInformation_repl	*reply;
	struct mapi_session			*session;
	mapi_object_message_t			*message;
	struct SPropValue			lpProp;
	NTSTATUS				status;
	enum MAPISTATUS				retval;
	uint32_t				size = 0;
	TALLOC_CTX				*mem_ctx;
	uint32_t				i = 0;
	uint8_t					logon_id;

	/* Sanity checks */
	OPENCHANGE_RETVAL_IF(!obj_message, MAPI_E_INVALID_PARAMETER, NULL);
	session = mapi_object_get_session(obj_message);
	OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);

	mapi_ctx = session->mapi_ctx;
	OPENCHANGE_RETVAL_IF(!mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);

	if ((retval = mapi_object_get_logon_id(obj_message, &logon_id)) != MAPI_E_SUCCESS)
		return retval;

	mem_ctx = talloc_named(session, 0, "ReloadCachedInformation");

	/* Fill the ReloadCachedInformation operation */
	request.Reserved = 0x0000;
	size += sizeof (uint16_t);

	/* Fill the MAPI_REQ request */
	mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
	mapi_req->opnum = op_MAPI_ReloadCachedInformation;
	mapi_req->logon_id = logon_id;
	mapi_req->handle_idx = 0;
	mapi_req->u.mapi_ReloadCachedInformation = request;
	size += 5;

	/* Fill the mapi_request structure */
	mapi_request = talloc_zero(mem_ctx, struct mapi_request);
	mapi_request->mapi_len = size + sizeof (uint32_t);
	mapi_request->length = size;
	mapi_request->mapi_req = mapi_req;
	mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
	mapi_request->handles[0] = mapi_object_get_handle(obj_message);

	status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
	OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
	OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
	retval = mapi_response->mapi_repl->error_code;

	OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);

	OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);

	/* Store ReloadCachedInformation reply data */
	reply = &mapi_response->mapi_repl->u.mapi_ReloadCachedInformation;

	message = talloc_zero((TALLOC_CTX *)session, mapi_object_message_t);
	message->cValues = reply->RecipientColumns.cValues;
	message->SRowSet.cRows = reply->RowCount;
	message->SRowSet.aRow = talloc_array((TALLOC_CTX *)message, struct SRow, reply->RowCount + 1);

	message->SPropTagArray.cValues = reply->RecipientColumns.cValues;
	message->SPropTagArray.aulPropTag = talloc_steal(message, reply->RecipientColumns.aulPropTag);

	for (i = 0; i < reply->RowCount; i++) {
		emsmdb_get_SRow((TALLOC_CTX *)message,
				&(message->SRowSet.aRow[i]), &message->SPropTagArray, 
				reply->RecipientRows[i].RecipientRow.prop_count,
				&reply->RecipientRows[i].RecipientRow.prop_values,
				reply->RecipientRows[i].RecipientRow.layout, 1);

		lpProp.ulPropTag = PR_RECIPIENT_TYPE;
		lpProp.value.l = reply->RecipientRows[i].RecipientType;
		SRow_addprop(&(message->SRowSet.aRow[i]), lpProp);

		lpProp.ulPropTag = PR_INTERNET_CPID;
		lpProp.value.l = reply->RecipientRows[i].CodePageId;
		SRow_addprop(&(message->SRowSet.aRow[i]), lpProp);
	}

	/* add SPropTagArray elements we automatically append to SRow */
	SPropTagArray_add((TALLOC_CTX *)message, &message->SPropTagArray, PR_RECIPIENT_TYPE);
	SPropTagArray_add((TALLOC_CTX *)message, &message->SPropTagArray, PR_INTERNET_CPID);

	talloc_free(obj_message->private_data);
	obj_message->private_data = (void *) message;

	talloc_free(mapi_response);
	talloc_free(mem_ctx);

	errno = 0;
	return MAPI_E_SUCCESS;
}
コード例 #29
0
static int
mod_authenticate (void *arg, eap_handler_t *handler)
{
    pwd_session_t *pwd_session;
    pwd_hdr *hdr;
    pwd_id_packet *id;
    eap_packet_t *response;
    REQUEST *request, *fake;
    VALUE_PAIR *pw, *vp;
    EAP_DS *eap_ds;
    int len, ret = 0;
    eap_pwd_t *inst = (eap_pwd_t *)arg;
    uint16_t offset;
    uint8_t exch, *buf, *ptr, msk[MSK_EMSK_LEN], emsk[MSK_EMSK_LEN];
    uint8_t peer_confirm[SHA256_DIGEST_LENGTH];
    BIGNUM *x = NULL, *y = NULL;

    if ((!handler) ||
	((eap_ds = handler->eap_ds) == NULL) ||
	(!inst)) {
	return 0;
    }
    pwd_session = (pwd_session_t *)handler->opaque;
    request = handler->request;
    response = handler->eap_ds->response;
    hdr = (pwd_hdr *)response->type.data;

    buf = hdr->data;
    len = response->type.length - sizeof(pwd_hdr);

    /*
     * see if we're fragmenting, if so continue until we're done
     */
    if (pwd_session->out_buf_pos) {
	if (len) {
	    RDEBUG2("pwd got something more than an ACK for a fragment");
	}
	return send_pwd_request(pwd_session, eap_ds);
    }

    /*
     * the first fragment will have a total length, make a
     * buffer to hold all the fragments
     */
    if (EAP_PWD_GET_LENGTH_BIT(hdr)) {
	if (pwd_session->in_buf) {
	    RDEBUG2("pwd already alloced buffer for fragments");
	    return 0;
	}
	pwd_session->in_buf_len = ntohs(buf[0] * 256 | buf[1]);
	if ((pwd_session->in_buf = talloc_zero_array(pwd_session, uint8_t,
						     pwd_session->in_buf_len)) == NULL) {
	    RDEBUG2("pwd cannot allocate %d buffer to hold fragments",
		    pwd_session->in_buf_len);
	    return 0;
	}
	memset(pwd_session->in_buf, 0, pwd_session->in_buf_len);
	pwd_session->in_buf_pos = 0;
	buf += sizeof(uint16_t);
	len -= sizeof(uint16_t);
    }

    /*
     * all fragments, including the 1st will have the M(ore) bit set,
     * buffer those fragments!
     */
    if (EAP_PWD_GET_MORE_BIT(hdr)) {
	rad_assert(pwd_session->in_buf != NULL);
	if ((pwd_session->in_buf_pos + len) > pwd_session->in_buf_len) {
	    RDEBUG2("pwd will not overflow a fragment buffer. Nope, not prudent.");
	    return 0;
	}
	memcpy(pwd_session->in_buf + pwd_session->in_buf_pos, buf, len);
	pwd_session->in_buf_pos += len;

	/*
	 * send back an ACK for this fragment
	 */
	exch = EAP_PWD_GET_EXCHANGE(hdr);
	eap_ds->request->code = PW_EAP_REQUEST;
	eap_ds->request->type.num = PW_EAP_PWD;
	eap_ds->request->type.length = sizeof(pwd_hdr);
	if ((eap_ds->request->type.data = talloc_array(eap_ds->request,
						       uint8_t, sizeof(pwd_hdr))) == NULL) {
	    return 0;
	}
	hdr = (pwd_hdr *)eap_ds->request->type.data;
	EAP_PWD_SET_EXCHANGE(hdr, exch);
	return 1;

    }

    if (pwd_session->in_buf) {
	/*
	 * the last fragment...
	 */
	if ((pwd_session->in_buf_pos + len) > pwd_session->in_buf_len) {
	    RDEBUG2("pwd will not overflow a fragment buffer. Nope, not prudent.");
	    return 0;
	}
	memcpy(pwd_session->in_buf + pwd_session->in_buf_pos, buf, len);
	buf = pwd_session->in_buf;
	len = pwd_session->in_buf_len;
    }

    switch (pwd_session->state) {
	case PWD_STATE_ID_REQ:
	    if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_ID) {
		RDEBUG2("pwd exchange is incorrect: not ID");
		return 0;
	    }
	    id = (pwd_id_packet *)buf;
	    if ((id->prf != EAP_PWD_DEF_PRF) ||
		(id->random_function != EAP_PWD_DEF_RAND_FUN) ||
		(id->prep != EAP_PWD_PREP_NONE) ||
		(memcmp(id->token, (char *)&pwd_session->token, 4)) ||
		(id->group_num != ntohs(pwd_session->group_num))) {
		RDEBUG2("pwd id response is invalid");
		return 0;
	    }
	    /*
	     * we've agreed on the ciphersuite, record it...
	     */
	    ptr = (uint8_t *)&pwd_session->ciphersuite;
	    memcpy(ptr, (char *)&id->group_num, sizeof(uint16_t));
	    ptr += sizeof(uint16_t);
	    *ptr = EAP_PWD_DEF_RAND_FUN;
	    ptr += sizeof(uint8_t);
	    *ptr = EAP_PWD_DEF_PRF;

	    pwd_session->peer_id_len = len - sizeof(pwd_id_packet);
	    if (pwd_session->peer_id_len >= sizeof(pwd_session->peer_id)) {
		RDEBUG2("pwd id response is malformed");
		return 0;
	    }
	    memcpy(pwd_session->peer_id, id->identity,
		    pwd_session->peer_id_len);
	    pwd_session->peer_id[pwd_session->peer_id_len] = '\0';

	    /*
	     * make fake request to get the password for the usable ID
	     */
	    if ((fake = request_alloc_fake(handler->request)) == NULL) {
		RDEBUG("pwd unable to create fake request!");
		return 0;
	    }
	    fake->username = pairmake_packet("User-Name", "", T_OP_EQ);
	    if (!fake->username) {
		RDEBUG("pwd unanable to create value pair for username!");
		request_free(&fake);
		return 0;
	    }
	    memcpy(fake->username->vp_strvalue, pwd_session->peer_id,
		   pwd_session->peer_id_len);
	    fake->username->length = pwd_session->peer_id_len;
	    fake->username->vp_strvalue[fake->username->length] = 0;

	    if ((vp = pairfind(request->config_items, PW_VIRTUAL_SERVER, 0, TAG_ANY)) != NULL) {
		    fake->server = vp->vp_strvalue;
		
	    } else if (inst->conf->virtual_server) {
		    fake->server = inst->conf->virtual_server;
		
	    } /* else fake->server == request->server */
	
	    if ((debug_flag > 0) && fr_log_fp) {
		    RDEBUG("Sending tunneled request");
		
		    debug_pair_list(fake->packet->vps);
		
		    fprintf(fr_log_fp, "server %s {\n",
			    (!fake->server) ? "" : fake->server);
	    }
	
	    /*
	     *	Call authorization recursively, which will
	     *	get the password.
	     */
	    process_authorize(0, fake);
	
	    /*
	     *	Note that we don't do *anything* with the reply
	     *	attributes.
	     */
	    if ((debug_flag > 0) && fr_log_fp) {
		    fprintf(fr_log_fp, "} # server %s\n",
			    (!fake->server) ? "" : fake->server);
		
		    RDEBUG("Got tunneled reply code %d", fake->reply->code);
		
		    debug_pair_list(fake->reply->vps);
	    }

	    if ((pw = pairfind(fake->config_items, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) == NULL) {
		DEBUG2("failed to find password for %s to do pwd authentication",
		       pwd_session->peer_id);
		request_free(&fake);
		return 0;
	    }

	    if (compute_password_element(pwd_session, pwd_session->group_num,
					 pw->data.strvalue, strlen(pw->data.strvalue),
					 inst->conf->server_id, strlen(inst->conf->server_id),
					 pwd_session->peer_id, strlen(pwd_session->peer_id),
					 &pwd_session->token)) {
		DEBUG2("failed to obtain password element :-(");
		request_free(&fake);
		return 0;
	    }
	    request_free(&fake);

	    /*
	     * compute our scalar and element
	     */
	    if (compute_scalar_element(pwd_session, inst->bnctx)) {
		DEBUG2("failed to compute server's scalar and element");
		return 0;
	    }
	    if (((x = BN_new()) == NULL) ||
		((y = BN_new()) == NULL)) {
		DEBUG2("server point allocation failed");
		return 0;
	    }
	    /*
	     * element is a point, get both coordinates: x and y
	     */
	    if (!EC_POINT_get_affine_coordinates_GFp(pwd_session->group,
						     pwd_session->my_element, x, y,
						     inst->bnctx)) {
		DEBUG2("server point assignment failed");
		BN_free(x);
		BN_free(y);
		return 0;
	    }
	    /*
	     * construct request
	     */
	    pwd_session->out_buf_len = BN_num_bytes(pwd_session->order) +
		(2 * BN_num_bytes(pwd_session->prime));
	    if ((pwd_session->out_buf = talloc_array(pwd_session, uint8_t,
						     pwd_session->out_buf_len)) == NULL) {
		return 0;
	    }
	    memset(pwd_session->out_buf, 0, pwd_session->out_buf_len);

	    ptr = pwd_session->out_buf;
	    offset = BN_num_bytes(pwd_session->prime) - BN_num_bytes(x);
	    BN_bn2bin(x, ptr + offset);

	    ptr += BN_num_bytes(pwd_session->prime);
	    offset = BN_num_bytes(pwd_session->prime) - BN_num_bytes(y);
	    BN_bn2bin(y, ptr + offset);

	    ptr += BN_num_bytes(pwd_session->prime);
	    offset = BN_num_bytes(pwd_session->order) - BN_num_bytes(pwd_session->my_scalar);
	    BN_bn2bin(pwd_session->my_scalar, ptr + offset);

	    pwd_session->state = PWD_STATE_COMMIT;
	    ret = send_pwd_request(pwd_session, eap_ds);
	    break;
	case PWD_STATE_COMMIT:
	    if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_COMMIT) {
		RDEBUG2("pwd exchange is incorrect: not commit!");
		return 0;
	    }
	    /*
	     * process the peer's commit and generate the shared key, k
	     */
	    if (process_peer_commit(pwd_session, buf, inst->bnctx)) {
		RDEBUG2("failed to process peer's commit");
		return 0;
	    }

	    /*
	     * compute our confirm blob
	     */
	    if (compute_server_confirm(pwd_session, pwd_session->my_confirm, inst->bnctx)) {
		ERROR("rlm_eap_pwd: failed to compute confirm!");
		return 0;
	    }
	    /*
	     * construct a response...which is just our confirm blob
	     */
	    pwd_session->out_buf_len = SHA256_DIGEST_LENGTH;
	    if ((pwd_session->out_buf = talloc_array(pwd_session, uint8_t,
						     pwd_session->out_buf_len)) == NULL) {
		return 0;
	    }
	    memset(pwd_session->out_buf, 0, pwd_session->out_buf_len);
	    memcpy(pwd_session->out_buf, pwd_session->my_confirm, SHA256_DIGEST_LENGTH);

	    pwd_session->state = PWD_STATE_CONFIRM;
	    ret = send_pwd_request(pwd_session, eap_ds);
	    break;
	case PWD_STATE_CONFIRM:
	    if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_CONFIRM) {
		RDEBUG2("pwd exchange is incorrect: not commit!");
		return 0;
	    }
	    if (compute_peer_confirm(pwd_session, peer_confirm, inst->bnctx)) {
		RDEBUG2("pwd exchange cannot compute peer's confirm");
		return 0;
	    }
	    if (memcmp(peer_confirm, buf, SHA256_DIGEST_LENGTH)) {
		RDEBUG2("pwd exchange fails: peer confirm is incorrect!");
		return 0;
	    }
	    if (compute_keys(pwd_session, peer_confirm, msk, emsk)) {
		RDEBUG2("pwd exchange cannot generate (E)MSK!");
		return 0;
	    }
	    eap_ds->request->code = PW_EAP_SUCCESS;
	    /*
	     * return the MSK (in halves)
	     */
	    eap_add_reply(handler->request,
			  "MS-MPPE-Recv-Key", msk, MPPE_KEY_LEN);
	    eap_add_reply(handler->request,
			  "MS-MPPE-Send-Key", msk+MPPE_KEY_LEN, MPPE_KEY_LEN);
	    ret = 1;
	    break;
	default:
	    RDEBUG2("unknown PWD state");
	    return 0;
    }

    /*
     * we processed the buffered fragments, get rid of them
     */
    if (pwd_session->in_buf) {
	    talloc_free(pwd_session->in_buf);
	    pwd_session->in_buf = NULL;
    }

    return ret;
}
コード例 #30
0
ファイル: pvfs_util.c プロジェクト: Arkhont/samba
/*
  copy a file. Caller is supposed to have already ensured that the
  operation is allowed. The destination file must not exist.
*/
NTSTATUS pvfs_copy_file(struct pvfs_state *pvfs,
			struct pvfs_filename *name1, 
			struct pvfs_filename *name2)
{
	int fd1, fd2;
	mode_t mode;
	NTSTATUS status;
	size_t buf_size = 0x10000;
	uint8_t *buf = talloc_array(name2, uint8_t, buf_size);

	if (buf == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	fd1 = pvfs_sys_open(pvfs, name1->full_name, O_RDONLY, 0);
	if (fd1 == -1) {
		talloc_free(buf);
		return pvfs_map_errno(pvfs, errno);
	}

	fd2 = pvfs_sys_open(pvfs, name2->full_name, O_CREAT|O_EXCL|O_WRONLY, 0);
	if (fd2 == -1) {
		close(fd1);
		talloc_free(buf);
		return pvfs_map_errno(pvfs, errno);
	}

	while (1) {
		ssize_t ret2, ret = read(fd1, buf, buf_size);
		if (ret == -1 && 
		    (errno == EINTR || errno == EAGAIN)) {
			continue;
		}
		if (ret <= 0) break;

		ret2 = write(fd2, buf, ret);
		if (ret2 == -1 &&
		    (errno == EINTR || errno == EAGAIN)) {
			continue;
		}
		
		if (ret2 != ret) {
			close(fd1);
			close(fd2);
			talloc_free(buf);
			pvfs_sys_unlink(pvfs, name2->full_name);
			if (ret2 == -1) {
				return pvfs_map_errno(pvfs, errno);
			}
			return NT_STATUS_DISK_FULL;
		}
	}

	talloc_free(buf);
	close(fd1);

	mode = pvfs_fileperms(pvfs, name1->dos.attrib);
	if (pvfs_sys_fchmod(pvfs, fd2, mode) == -1) {
		status = pvfs_map_errno(pvfs, errno);
		close(fd2);
		pvfs_sys_unlink(pvfs, name2->full_name);
		return status;
	}

	name2->st.st_mode = mode;
	name2->dos = name1->dos;

	status = pvfs_dosattrib_save(pvfs, name2, fd2);
	if (!NT_STATUS_IS_OK(status)) {
		close(fd2);
		pvfs_sys_unlink(pvfs, name2->full_name);
		return status;
	}

	close(fd2);

	return NT_STATUS_OK;
}