#include <libmlrpc.h>
#include <sys/sysmacros.h>
#include <strings.h>
int
ndr_add_auth_token(ndr_auth_ctx_t *ctx, ndr_xa_t *mxa)
{
ndr_stream_t *nds = &mxa->send_nds;
ndr_sec_t *secp = &mxa->send_auth;
secp->auth_type = ctx->auth_type;
secp->auth_level = ctx->auth_level;
secp->auth_rsvd = 0;
secp->auth_pad_len = P2ROUNDUP(nds->pdu_scan_offset, 16) -
nds->pdu_scan_offset;
if (NDS_PAD_PDU(nds, nds->pdu_scan_offset,
secp->auth_pad_len, NULL) == 0)
return (NDR_DRC_FAULT_SEC_ENCODE_TOO_BIG);
nds->pdu_scan_offset += secp->auth_pad_len;
nds->pdu_body_size = nds->pdu_scan_offset -
nds->pdu_body_offset;
secp->auth_context_id = ctx->auth_context_id;
return (NDR_DRC_OK);
}
int
ndr_add_sec_context(ndr_auth_ctx_t *ctx, ndr_xa_t *mxa)
{
int rc;
if (ctx->auth_level == NDR_C_AUTHN_NONE ||
ctx->auth_type == NDR_C_AUTHN_NONE)
return (NDR_DRC_OK);
if (ctx->auth_type != NDR_C_AUTHN_GSS_NETLOGON)
return (NDR_DRC_FAULT_SEC_TYPE_UNIMPLEMENTED);
if (ctx->auth_level != NDR_C_AUTHN_LEVEL_PKT_INTEGRITY &&
ctx->auth_level != NDR_C_AUTHN_LEVEL_PKT_PRIVACY)
return (NDR_DRC_FAULT_SEC_LEVEL_UNIMPLEMENTED);
if ((rc = ndr_add_auth_token(ctx, mxa)) != 0)
return (rc);
return (ctx->auth_ops.nao_init(ctx->auth_ctx, mxa));
}
int
ndr_recv_sec_context(ndr_auth_ctx_t *ctx, ndr_xa_t *mxa)
{
ndr_sec_t *bind_secp = &mxa->send_auth;
ndr_sec_t *ack_secp = &mxa->recv_auth;
if (ctx->auth_level == NDR_C_AUTHN_NONE ||
ctx->auth_type == NDR_C_AUTHN_NONE) {
if (mxa->recv_hdr.common_hdr.auth_length != 0)
return (NDR_DRC_FAULT_SEC_AUTH_LENGTH_INVALID);
return (NDR_DRC_OK);
} else if (mxa->recv_hdr.common_hdr.auth_length == 0) {
return (NDR_DRC_FAULT_SEC_AUTH_LENGTH_INVALID);
}
if (bind_secp->auth_type != ack_secp->auth_type)
return (NDR_DRC_FAULT_SEC_AUTH_TYPE_INVALID);
if (bind_secp->auth_level != ack_secp->auth_level)
return (NDR_DRC_FAULT_SEC_AUTH_LEVEL_INVALID);
return (ctx->auth_ops.nao_recv(ctx->auth_ctx, mxa));
}
int
ndr_add_auth(ndr_auth_ctx_t *ctx, ndr_xa_t *mxa)
{
int rc;
if (ctx->auth_level == NDR_C_AUTHN_NONE ||
ctx->auth_type == NDR_C_AUTHN_NONE)
return (NDR_DRC_OK);
if (ctx->auth_type != NDR_C_AUTHN_GSS_NETLOGON)
return (NDR_DRC_FAULT_SEC_TYPE_UNIMPLEMENTED);
if (ctx->auth_level != NDR_C_AUTHN_LEVEL_PKT_INTEGRITY &&
ctx->auth_level != NDR_C_AUTHN_LEVEL_PKT_PRIVACY)
return (NDR_DRC_FAULT_SEC_LEVEL_UNIMPLEMENTED);
if ((rc = ndr_add_auth_token(ctx, mxa)) != 0)
return (rc);
if (ctx->auth_level == NDR_C_AUTHN_LEVEL_PKT_PRIVACY)
return (ctx->auth_ops.nao_encrypt(ctx->auth_ctx, mxa));
return (ctx->auth_ops.nao_sign(ctx->auth_ctx, mxa));
}
int
ndr_check_auth(ndr_auth_ctx_t *ctx, ndr_xa_t *mxa)
{
ndr_sec_t *secp = &mxa->recv_auth;
if (ctx->auth_level == NDR_C_AUTHN_NONE ||
ctx->auth_type == NDR_C_AUTHN_NONE) {
if (mxa->recv_hdr.common_hdr.auth_length != 0)
return (NDR_DRC_FAULT_SEC_AUTH_LENGTH_INVALID);
return (NDR_DRC_OK);
} else if (mxa->recv_hdr.common_hdr.auth_length == 0) {
return (NDR_DRC_FAULT_SEC_AUTH_LENGTH_INVALID);
}
if (ctx->auth_type != secp->auth_type ||
ctx->auth_type != NDR_C_AUTHN_GSS_NETLOGON)
return (NDR_DRC_FAULT_SEC_AUTH_TYPE_INVALID);
if (ctx->auth_level != secp->auth_level ||
(ctx->auth_level != NDR_C_AUTHN_LEVEL_PKT_INTEGRITY &&
ctx->auth_level != NDR_C_AUTHN_LEVEL_PKT_PRIVACY))
return (NDR_DRC_FAULT_SEC_AUTH_LEVEL_INVALID);
if (ctx->auth_level == NDR_C_AUTHN_LEVEL_PKT_PRIVACY)
return (ctx->auth_ops.nao_decrypt(ctx->auth_ctx, mxa,
ctx->auth_verify_resp));
return (ctx->auth_ops.nao_verify(ctx->auth_ctx, mxa,
ctx->auth_verify_resp));
}