Example #1
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;
}
Example #2
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;
}