1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2020 Tintri by DDN, Inc. All Rights Reserved. 14 * Copyright 2023 RackTop Systems, Inc. 15 */ 16 17 #include <libmlrpc.h> 18 #include <sys/sysmacros.h> 19 #include <strings.h> 20 21 /* 22 * Initializes the sec_trailer (ndr_sec_t). 23 * The actual token is allocated and set later (in the SSP). 24 */ 25 int 26 ndr_add_auth_token(ndr_auth_ctx_t *ctx, ndr_xa_t *mxa) 27 { 28 ndr_stream_t *nds = &mxa->send_nds; 29 ndr_sec_t *secp = &mxa->send_auth; 30 31 secp->auth_type = ctx->auth_type; 32 secp->auth_level = ctx->auth_level; 33 secp->auth_rsvd = 0; 34 35 /* 36 * [MS-RPCE] 2.2.2.12 "Authentication Tokens" 37 * auth_pad_len aligns the packet to 16 bytes. 38 */ 39 secp->auth_pad_len = P2ROUNDUP(nds->pdu_scan_offset, 16) - 40 nds->pdu_scan_offset; 41 if (NDS_PAD_PDU(nds, nds->pdu_scan_offset, 42 secp->auth_pad_len, NULL) == 0) 43 return (NDR_DRC_FAULT_SEC_ENCODE_TOO_BIG); 44 45 /* PAD_PDU doesn't adjust scan_offset */ 46 nds->pdu_scan_offset += secp->auth_pad_len; 47 nds->pdu_body_size = nds->pdu_scan_offset - 48 nds->pdu_body_offset; 49 50 secp->auth_context_id = ctx->auth_context_id; 51 return (NDR_DRC_OK); 52 } 53 54 /* 55 * Does gss_init_sec_context (or equivalent) and creates 56 * the sec_trailer and the auth token. 57 * 58 * Used during binds (and alter context). 59 * 60 * Currently, only NETLOGON auth with Integrity/Privacy protection 61 * is implemented. 62 */ 63 int 64 ndr_add_sec_context(ndr_auth_ctx_t *ctx, ndr_xa_t *mxa) 65 { 66 int rc; 67 68 if (ctx->auth_level == NDR_C_AUTHN_NONE || 69 ctx->auth_type == NDR_C_AUTHN_NONE) 70 return (NDR_DRC_OK); 71 72 if (ctx->auth_type != NDR_C_AUTHN_GSS_NETLOGON) 73 return (NDR_DRC_FAULT_SEC_TYPE_UNIMPLEMENTED); 74 75 if (ctx->auth_level != NDR_C_AUTHN_LEVEL_PKT_INTEGRITY && 76 ctx->auth_level != NDR_C_AUTHN_LEVEL_PKT_PRIVACY) 77 return (NDR_DRC_FAULT_SEC_LEVEL_UNIMPLEMENTED); 78 79 if ((rc = ndr_add_auth_token(ctx, mxa)) != 0) 80 return (rc); 81 82 return (ctx->auth_ops.nao_init(ctx->auth_ctx, mxa)); 83 } 84 85 /* 86 * Does response-side gss_init_sec_context (or equivalent) and validates 87 * the sec_trailer and the auth token. 88 * 89 * Used during bind (and alter context) ACKs. 90 */ 91 int 92 ndr_recv_sec_context(ndr_auth_ctx_t *ctx, ndr_xa_t *mxa) 93 { 94 ndr_sec_t *bind_secp = &mxa->send_auth; 95 ndr_sec_t *ack_secp = &mxa->recv_auth; 96 97 if (ctx->auth_level == NDR_C_AUTHN_NONE || 98 ctx->auth_type == NDR_C_AUTHN_NONE) { 99 if (mxa->recv_hdr.common_hdr.auth_length != 0) 100 return (NDR_DRC_FAULT_SEC_AUTH_LENGTH_INVALID); 101 return (NDR_DRC_OK); 102 } else if (mxa->recv_hdr.common_hdr.auth_length == 0) { 103 return (NDR_DRC_FAULT_SEC_AUTH_LENGTH_INVALID); 104 } 105 106 if (bind_secp->auth_type != ack_secp->auth_type) 107 return (NDR_DRC_FAULT_SEC_AUTH_TYPE_INVALID); 108 if (bind_secp->auth_level != ack_secp->auth_level) 109 return (NDR_DRC_FAULT_SEC_AUTH_LEVEL_INVALID); 110 111 return (ctx->auth_ops.nao_recv(ctx->auth_ctx, mxa)); 112 } 113 114 /* 115 * Does gss_MICEx (or equivalent) and creates 116 * the sec_trailer and the auth token. 117 * 118 * Used upon sending a request (client)/response (server) packet. 119 */ 120 int 121 ndr_add_auth(ndr_auth_ctx_t *ctx, ndr_xa_t *mxa) 122 { 123 int rc; 124 125 if (ctx->auth_level == NDR_C_AUTHN_NONE || 126 ctx->auth_type == NDR_C_AUTHN_NONE) 127 return (NDR_DRC_OK); 128 129 if (ctx->auth_type != NDR_C_AUTHN_GSS_NETLOGON) 130 return (NDR_DRC_FAULT_SEC_TYPE_UNIMPLEMENTED); 131 132 if (ctx->auth_level != NDR_C_AUTHN_LEVEL_PKT_INTEGRITY && 133 ctx->auth_level != NDR_C_AUTHN_LEVEL_PKT_PRIVACY) 134 return (NDR_DRC_FAULT_SEC_LEVEL_UNIMPLEMENTED); 135 136 if ((rc = ndr_add_auth_token(ctx, mxa)) != 0) 137 return (rc); 138 139 if (ctx->auth_level == NDR_C_AUTHN_LEVEL_PKT_PRIVACY) 140 return (ctx->auth_ops.nao_encrypt(ctx->auth_ctx, mxa)); 141 return (ctx->auth_ops.nao_sign(ctx->auth_ctx, mxa)); 142 } 143 144 /* 145 * Does gss_VerifyMICEx (or equivalent) and validates 146 * the sec_trailer and the auth token. 147 * 148 * Used upon receiving a request (server)/response (client) packet. 149 * 150 * If auth_verify_resp is B_FALSE, this doesn't verify responses (but 151 * the SSP may still have side-effects). 152 */ 153 int 154 ndr_check_auth(ndr_auth_ctx_t *ctx, ndr_xa_t *mxa) 155 { 156 ndr_sec_t *secp = &mxa->recv_auth; 157 158 if (ctx->auth_level == NDR_C_AUTHN_NONE || 159 ctx->auth_type == NDR_C_AUTHN_NONE) { 160 if (mxa->recv_hdr.common_hdr.auth_length != 0) 161 return (NDR_DRC_FAULT_SEC_AUTH_LENGTH_INVALID); 162 return (NDR_DRC_OK); 163 } else if (mxa->recv_hdr.common_hdr.auth_length == 0) { 164 return (NDR_DRC_FAULT_SEC_AUTH_LENGTH_INVALID); 165 } 166 167 if (ctx->auth_type != secp->auth_type || 168 ctx->auth_type != NDR_C_AUTHN_GSS_NETLOGON) 169 return (NDR_DRC_FAULT_SEC_AUTH_TYPE_INVALID); 170 171 if (ctx->auth_level != secp->auth_level || 172 (ctx->auth_level != NDR_C_AUTHN_LEVEL_PKT_INTEGRITY && 173 ctx->auth_level != NDR_C_AUTHN_LEVEL_PKT_PRIVACY)) 174 return (NDR_DRC_FAULT_SEC_AUTH_LEVEL_INVALID); 175 176 if (ctx->auth_level == NDR_C_AUTHN_LEVEL_PKT_PRIVACY) 177 return (ctx->auth_ops.nao_decrypt(ctx->auth_ctx, mxa, 178 ctx->auth_verify_resp)); 179 return (ctx->auth_ops.nao_verify(ctx->auth_ctx, mxa, 180 ctx->auth_verify_resp)); 181 } 182