Пример #1
0
static NTSTATUS common_gss_decrypt_buffer(struct smb_tran_enc_state_gss *gss_state, char *buf)
{
	gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
	OM_uint32 ret = 0;
	OM_uint32 minor = 0;
	int flags_got = 0;
	gss_buffer_desc in_buf, out_buf;
	size_t buf_len = smb_len_nbt(buf) + 4; /* Don't forget the 4 length bytes. */

	if (buf_len < 8) {
		return NT_STATUS_BUFFER_TOO_SMALL;
	}

	in_buf.value = buf + 8;
	in_buf.length = buf_len - 8;

	ret = gss_unwrap(&minor,
			gss_ctx,
			&in_buf,
			&out_buf,
			&flags_got,		/* did we get sign+seal ? */
			(gss_qop_t *) NULL);

	if (ret != GSS_S_COMPLETE) {
		NTSTATUS status = NT_STATUS_ACCESS_DENIED;
		char *gss_err;

		gss_err = gssapi_error_string(talloc_tos(),
					      ret, minor,
					      GSS_C_NULL_OID);
		DEBUG(0,("common_gss_decrypt_buffer: gss_unwrap failed. "
			 "Error [%d/%d] - %s - %s\n",
			 ret, minor, nt_errstr(status),
			 gss_err ? gss_err : "<unknown>"));
		talloc_free(gss_err);

		return status;
	}

	if (out_buf.length > in_buf.length) {
		DEBUG(0,("common_gss_decrypt_buffer: gss_unwrap size (%u) too large (%u) !\n",
			(unsigned int)out_buf.length,
			(unsigned int)in_buf.length ));
		gss_release_buffer(&minor, &out_buf);
		return NT_STATUS_INVALID_PARAMETER;
	}

	memcpy(buf + 8, out_buf.value, out_buf.length);
	/* Reset the length and overwrite the header. */
	smb_setlen_nbt(buf, out_buf.length + 4);

	gss_release_buffer(&minor, &out_buf);
	return NT_STATUS_OK;
}
Пример #2
0
NTSTATUS get_enc_ctx_num(const uint8_t *buf, uint16_t *p_enc_ctx_num)
{
	if (smb_len_nbt(buf) < 8) {
		return NT_STATUS_INVALID_BUFFER_SIZE;
	}

	if (buf[4] == 0xFF) {
		if (buf[5] == 'S' && buf [6] == 'M' && buf[7] == 'B') {
			/* Not an encrypted buffer. */
			return NT_STATUS_NOT_FOUND;
		}
		if (buf[5] == 'E') {
			*p_enc_ctx_num = SVAL(buf,6);
			return NT_STATUS_OK;
		}
	}
	return NT_STATUS_INVALID_NETWORK_RESPONSE;
}
Пример #3
0
static NTSTATUS common_gensec_decrypt_buffer(struct gensec_security *gensec,
					     char *buf)
{
	NTSTATUS status;
	size_t buf_len = smb_len_nbt(buf) + 4; /* Don't forget the 4 length bytes. */
	DATA_BLOB in_buf, out_buf;
	TALLOC_CTX *frame;

	if (buf_len < 8) {
		return NT_STATUS_BUFFER_TOO_SMALL;
	}

	frame = talloc_stackframe();

	in_buf = data_blob_const(buf + 8, buf_len - 8);

	status = gensec_unwrap(gensec, frame, &in_buf, &out_buf);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("common_gensec_decrypt_buffer: gensec_unwrap failed. Error %s\n",
			 nt_errstr(status)));
		TALLOC_FREE(frame);
		return status;
	}

	if (out_buf.length > in_buf.length) {
		DEBUG(0,("common_gensec_decrypt_buffer: gensec_unwrap size (%u) too large (%u) !\n",
			(unsigned int)out_buf.length,
			(unsigned int)in_buf.length ));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_PARAMETER;
	}

	memcpy(buf + 8, out_buf.data, out_buf.length);

	/* Reset the length and overwrite the header. */
	smb_setlen_nbt(buf, out_buf.length + 4);

	TALLOC_FREE(frame);

	return NT_STATUS_OK;
}
Пример #4
0
static NTSTATUS common_gensec_encrypt_buffer(struct gensec_security *gensec,
				      uint16_t enc_ctx_num,
				      char *buf,
				      char **ppbuf_out)
{
	NTSTATUS status;
	DATA_BLOB in_buf, out_buf;
	size_t buf_len = smb_len_nbt(buf) + 4; /* Don't forget the 4 length bytes. */
	TALLOC_CTX *frame;

	*ppbuf_out = NULL;

	if (buf_len < 8) {
		return NT_STATUS_BUFFER_TOO_SMALL;
	}
	in_buf = data_blob_const(buf + 8, buf_len - 8);

	frame = talloc_stackframe();

	status = gensec_wrap(gensec, frame, &in_buf, &out_buf);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("common_gensec_encrypt_buffer: gensec_wrap failed. Error %s\n",
			 nt_errstr(status)));
		TALLOC_FREE(frame);
		return status;
	}

	*ppbuf_out = (char *)malloc(out_buf.length + 8); /* We know this can't wrap. */
	if (!*ppbuf_out) {
		TALLOC_FREE(frame);
		return NT_STATUS_NO_MEMORY;
	}

	memcpy(*ppbuf_out+8, out_buf.data, out_buf.length);
	smb_set_enclen(*ppbuf_out, out_buf.length + 4, enc_ctx_num);

	TALLOC_FREE(frame);

	return NT_STATUS_OK;
}
Пример #5
0
static NTSTATUS common_gss_encrypt_buffer(struct smb_tran_enc_state_gss *gss_state,
					uint16_t enc_ctx_num,
					char *buf,
					char **ppbuf_out)
{
	gss_ctx_id_t gss_ctx = gss_state->gss_ctx;
	OM_uint32 ret = 0;
	OM_uint32 minor = 0;
	int flags_got = 0;
	gss_buffer_desc in_buf, out_buf;
	size_t buf_len = smb_len_nbt(buf) + 4; /* Don't forget the 4 length bytes. */

	*ppbuf_out = NULL;

	if (buf_len < 8) {
		return NT_STATUS_BUFFER_TOO_SMALL;
	}

	in_buf.value = buf + 8;
	in_buf.length = buf_len - 8;

	ret = gss_wrap(&minor,
			gss_ctx,
			true,			/* we want sign+seal. */
			GSS_C_QOP_DEFAULT,
			&in_buf,
			&flags_got,		/* did we get sign+seal ? */
			&out_buf);

	if (ret != GSS_S_COMPLETE) {
		NTSTATUS status = NT_STATUS_ACCESS_DENIED;
		char *gss_err;

		gss_err = gssapi_error_string(talloc_tos(),
					      ret, minor,
					      GSS_C_NULL_OID);
		DEBUG(0,("common_gss_encrypt_buffer: gss_unwrap failed. "
			 "Error [%d/%d] - %s - %s\n",
			 ret, minor, nt_errstr(status),
			 gss_err ? gss_err : "<unknown>"));
		talloc_free(gss_err);

		return status;
	}

	if (!flags_got) {
		/* Sign+seal not supported. */
		gss_release_buffer(&minor, &out_buf);
		return NT_STATUS_NOT_SUPPORTED;
	}

	/* Ya see - this is why I *hate* gss-api. I don't
	 * want to have to malloc another buffer of the
	 * same size + 8 bytes just to get a continuous
	 * header + buffer, but gss won't let me pass in
	 * a pre-allocated buffer. Bastards (and you know
	 * who you are....). I might fix this by
	 * going to "encrypt_and_send" passing in a file
	 * descriptor and doing scatter-gather write with
	 * TCP cork on Linux. But I shouldn't have to
	 * bother :-*(. JRA.
	 */

	*ppbuf_out = (char *)malloc(out_buf.length + 8); /* We know this can't wrap. */
	if (!*ppbuf_out) {
		gss_release_buffer(&minor, &out_buf);
		return NT_STATUS_NO_MEMORY;
	}

	memcpy(*ppbuf_out+8, out_buf.value, out_buf.length);
	smb_set_enclen(*ppbuf_out, out_buf.length + 4, enc_ctx_num);

	gss_release_buffer(&minor, &out_buf);
	return NT_STATUS_OK;
}