dcesrv_auth.c

来自「samba最新软件」· C语言 代码 · 共 533 行 · 第 1/2 页

C
533
字号
	DEBUG(2, ("Failed to finish dcesrv auth alter_ack: %s\n", nt_errstr(status)));	return status;}/*  generate a CONNECT level verifier*/static NTSTATUS dcesrv_connect_verifier(TALLOC_CTX *mem_ctx, DATA_BLOB *blob){	*blob = data_blob_talloc(mem_ctx, NULL, 16);	if (blob->data == NULL) {		return NT_STATUS_NO_MEMORY;	}	SIVAL(blob->data, 0, 1);	memset(blob->data+4, 0, 12);	return NT_STATUS_OK;}/*  generate a CONNECT level verifier*/static NTSTATUS dcesrv_check_connect_verifier(DATA_BLOB *blob){	if (blob->length != 16 ||	    IVAL(blob->data, 0) != 1) {		return NT_STATUS_ACCESS_DENIED;	}	return NT_STATUS_OK;}/*  check credentials on a request*/bool dcesrv_auth_request(struct dcesrv_call_state *call, DATA_BLOB *full_packet){	struct ncacn_packet *pkt = &call->pkt;	struct dcesrv_connection *dce_conn = call->conn;	DATA_BLOB auth_blob;	struct dcerpc_auth auth;	struct ndr_pull *ndr;	NTSTATUS status;	enum ndr_err_code ndr_err;	if (!dce_conn->auth_state.auth_info ||	    !dce_conn->auth_state.gensec_security) {		return true;	}	auth_blob.length = 8 + pkt->auth_length;	/* check for a valid length */	if (pkt->u.request.stub_and_verifier.length < auth_blob.length) {		return false;	}	auth_blob.data = 		pkt->u.request.stub_and_verifier.data + 		pkt->u.request.stub_and_verifier.length - auth_blob.length;	pkt->u.request.stub_and_verifier.length -= auth_blob.length;	/* pull the auth structure */	ndr = ndr_pull_init_blob(&auth_blob, call, lp_iconv_convenience(call->conn->dce_ctx->lp_ctx));	if (!ndr) {		return false;	}	if (!(pkt->drep[0] & DCERPC_DREP_LE)) {		ndr->flags |= LIBNDR_FLAG_BIGENDIAN;	}	ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, &auth);	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {		talloc_free(ndr);		return false;	}	/* check signature or unseal the packet */	switch (dce_conn->auth_state.auth_info->auth_level) {	case DCERPC_AUTH_LEVEL_PRIVACY:		status = gensec_unseal_packet(dce_conn->auth_state.gensec_security,					      call,					      full_packet->data + DCERPC_REQUEST_LENGTH,					      pkt->u.request.stub_and_verifier.length, 					      full_packet->data,					      full_packet->length-auth.credentials.length,					      &auth.credentials);		memcpy(pkt->u.request.stub_and_verifier.data, 		       full_packet->data + DCERPC_REQUEST_LENGTH,		       pkt->u.request.stub_and_verifier.length);		break;	case DCERPC_AUTH_LEVEL_INTEGRITY:		status = gensec_check_packet(dce_conn->auth_state.gensec_security,					     call,					     pkt->u.request.stub_and_verifier.data, 					     pkt->u.request.stub_and_verifier.length,					     full_packet->data,					     full_packet->length-auth.credentials.length,					     &auth.credentials);		break;	case DCERPC_AUTH_LEVEL_CONNECT:		status = dcesrv_check_connect_verifier(&auth.credentials);		break;	default:		status = NT_STATUS_INVALID_LEVEL;		break;	}	/* remove the indicated amount of padding */	if (pkt->u.request.stub_and_verifier.length < auth.auth_pad_length) {		talloc_free(ndr);		return false;	}	pkt->u.request.stub_and_verifier.length -= auth.auth_pad_length;	talloc_free(ndr);	return NT_STATUS_IS_OK(status);}/*    push a signed or sealed dcerpc request packet into a blob*/bool dcesrv_auth_response(struct dcesrv_call_state *call,			  DATA_BLOB *blob, struct ncacn_packet *pkt){	struct dcesrv_connection *dce_conn = call->conn;	NTSTATUS status;	enum ndr_err_code ndr_err;	struct ndr_push *ndr;	uint32_t payload_length;	DATA_BLOB creds2;	/* non-signed packets are simple */	if (!dce_conn->auth_state.auth_info || !dce_conn->auth_state.gensec_security) {		status = ncacn_push_auth(blob, call, lp_iconv_convenience(dce_conn->dce_ctx->lp_ctx), pkt, NULL);		return NT_STATUS_IS_OK(status);	}	ndr = ndr_push_init_ctx(call, lp_iconv_convenience(dce_conn->dce_ctx->lp_ctx));	if (!ndr) {		return false;	}	if (!(pkt->drep[0] & DCERPC_DREP_LE)) {		ndr->flags |= LIBNDR_FLAG_BIGENDIAN;	}	ndr_err = ndr_push_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {		return false;	}	/* pad to 16 byte multiple, match win2k3 */	dce_conn->auth_state.auth_info->auth_pad_length = NDR_ALIGN(ndr, 16);	ndr_push_zero(ndr, dce_conn->auth_state.auth_info->auth_pad_length);	payload_length = ndr->offset - DCERPC_REQUEST_LENGTH;	if (dce_conn->auth_state.auth_info->auth_level == DCERPC_AUTH_LEVEL_CONNECT) {		status = dcesrv_connect_verifier(call,						 &dce_conn->auth_state.auth_info->credentials);		if (!NT_STATUS_IS_OK(status)) {			return false;		}	} else {		/* We hope this length is accruate.  If must be if the		 * GENSEC mech does AEAD signing of the packet		 * headers */		dce_conn->auth_state.auth_info->credentials			= data_blob_talloc(call, NULL, 					   gensec_sig_size(dce_conn->auth_state.gensec_security, 							   payload_length));		data_blob_clear(&dce_conn->auth_state.auth_info->credentials);	}	/* add the auth verifier */	ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS,				      dce_conn->auth_state.auth_info);	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {		return false;	}	/* extract the whole packet as a blob */	*blob = ndr_push_blob(ndr);	/* fill in the fragment length and auth_length, we can't fill	   in these earlier as we don't know the signature length (it	   could be variable length) */	dcerpc_set_frag_length(blob, blob->length);	/* We hope this value is accruate.  If must be if the GENSEC	 * mech does AEAD signing of the packet headers */	dcerpc_set_auth_length(blob, dce_conn->auth_state.auth_info->credentials.length);	/* sign or seal the packet */	switch (dce_conn->auth_state.auth_info->auth_level) {	case DCERPC_AUTH_LEVEL_PRIVACY:		status = gensec_seal_packet(dce_conn->auth_state.gensec_security, 					    call,					    ndr->data + DCERPC_REQUEST_LENGTH, 					    payload_length,					    blob->data,					    blob->length - dce_conn->auth_state.auth_info->credentials.length,					    &creds2);		if (NT_STATUS_IS_OK(status)) {			blob->length -= dce_conn->auth_state.auth_info->credentials.length;			if (!data_blob_append(call, blob, creds2.data, creds2.length))				status = NT_STATUS_NO_MEMORY;			else				status = NT_STATUS_OK;		}		/* If we did AEAD signing of the packet headers, then we hope		 * this value didn't change... */		dcerpc_set_auth_length(blob, creds2.length);		dcerpc_set_frag_length(blob, dcerpc_get_frag_length(blob)+creds2.length);		data_blob_free(&creds2);		break;	case DCERPC_AUTH_LEVEL_INTEGRITY:		status = gensec_sign_packet(dce_conn->auth_state.gensec_security, 					    call,					    ndr->data + DCERPC_REQUEST_LENGTH, 					    payload_length,					    blob->data,					    blob->length - dce_conn->auth_state.auth_info->credentials.length,					    &creds2);		if (NT_STATUS_IS_OK(status)) {			blob->length -= dce_conn->auth_state.auth_info->credentials.length;			if (!data_blob_append(call, blob, creds2.data, creds2.length))				status = NT_STATUS_NO_MEMORY;			else				status = NT_STATUS_OK;		}		/* If we did AEAD signing of the packet headers, then we hope		 * this value didn't change... */		dcerpc_set_auth_length(blob, creds2.length);		dcerpc_set_frag_length(blob, dcerpc_get_frag_length(blob)+creds2.length);		data_blob_free(&creds2);		break;	case DCERPC_AUTH_LEVEL_CONNECT:		break;	default:		status = NT_STATUS_INVALID_LEVEL;		break;	}	data_blob_free(&dce_conn->auth_state.auth_info->credentials);	if (!NT_STATUS_IS_OK(status)) {		return false;	}		return true;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?