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 */ 15 16 #include <libmlrpc.h> 17 #include <sys/sysmacros.h> 18 #include <strings.h> 19 20 /* 21 * Initializes the sec_trailer (ndr_sec_t). 22 * The actual token is allocated and set later (in the SSP). 23 */ 24 int 25 ndr_add_auth_token(ndr_auth_ctx_t *ctx, ndr_xa_t *mxa) 26 { 27 ndr_stream_t *nds = &mxa->send_nds; 28 ndr_sec_t *secp = &mxa->send_auth; 29 30 secp->auth_type = ctx->auth_type; 31 secp->auth_level = ctx->auth_level; 32 secp->auth_rsvd = 0; 33 34 /* 35 * [MS-RPCE] 2.2.2.12 "Authentication Tokens" 36 * auth_pad_len aligns the packet to 16 bytes. 37 */ 38 secp->auth_pad_len = P2ROUNDUP(nds->pdu_scan_offset, 16) - 39 nds->pdu_scan_offset; 40 if (NDS_PAD_PDU(nds, nds->pdu_scan_offset, 41 secp->auth_pad_len, NULL) == 0) 42 return (NDR_DRC_FAULT_SEC_ENCODE_TOO_BIG); 43 44 /* PAD_PDU doesn't adjust scan_offset */ 45 nds->pdu_scan_offset += secp->auth_pad_len; 46 nds->pdu_body_size = nds->pdu_scan_offset - 47 nds->pdu_body_offset; 48 49 secp->auth_context_id = ctx->auth_context_id; 50 return (NDR_DRC_OK); 51 } 52 53 /* 54 * Does gss_init_sec_context (or equivalent) and creates 55 * the sec_trailer and the auth token. 56 * 57 * Used during binds (and alter context). 58 * 59 * Currently, only NETLOGON auth with Integrity protection is implemented. 60 */ 61 int 62 ndr_add_sec_context(ndr_auth_ctx_t *ctx, ndr_xa_t *mxa) 63 { 64 int rc; 65 66 if (ctx->auth_level == NDR_C_AUTHN_NONE || 67 ctx->auth_type == NDR_C_AUTHN_NONE) 68 return (NDR_DRC_OK); 69 70 if (ctx->auth_type != NDR_C_AUTHN_GSS_NETLOGON) 71 return (NDR_DRC_FAULT_SEC_TYPE_UNIMPLEMENTED); 72 73 if (ctx->auth_level != NDR_C_AUTHN_LEVEL_PKT_INTEGRITY) 74 return (NDR_DRC_FAULT_SEC_LEVEL_UNIMPLEMENTED); 75 76 if ((rc = ndr_add_auth_token(ctx, mxa)) != 0) 77 return (rc); 78 79 return (ctx->auth_ops.nao_init(ctx->auth_ctx, mxa)); 80 } 81 82 /* 83 * Does response-side gss_init_sec_context (or equivalent) and validates 84 * the sec_trailer and the auth token. 85 * 86 * Used during bind (and alter context) ACKs. 87 */ 88 int 89 ndr_recv_sec_context(ndr_auth_ctx_t *ctx, ndr_xa_t *mxa) 90 { 91 ndr_sec_t *bind_secp = &mxa->send_auth; 92 ndr_sec_t *ack_secp = &mxa->recv_auth; 93 94 if (ctx->auth_level == NDR_C_AUTHN_NONE || 95 ctx->auth_type == NDR_C_AUTHN_NONE) { 96 if (mxa->recv_hdr.common_hdr.auth_length != 0) 97 return (NDR_DRC_FAULT_SEC_AUTH_LENGTH_INVALID); 98 return (NDR_DRC_OK); 99 } else if (mxa->recv_hdr.common_hdr.auth_length == 0) { 100 return (NDR_DRC_FAULT_SEC_AUTH_LENGTH_INVALID); 101 } 102 103 if (bind_secp->auth_type != ack_secp->auth_type) 104 return (NDR_DRC_FAULT_SEC_AUTH_TYPE_INVALID); 105 if (bind_secp->auth_level != ack_secp->auth_level) 106 return (NDR_DRC_FAULT_SEC_AUTH_LEVEL_INVALID); 107 108 return (ctx->auth_ops.nao_recv(ctx->auth_ctx, mxa)); 109 } 110 111 /* 112 * Does gss_MICEx (or equivalent) and creates 113 * the sec_trailer and the auth token. 114 * 115 * Used upon sending a request (client)/response (server) packet. 116 */ 117 int 118 ndr_add_auth(ndr_auth_ctx_t *ctx, ndr_xa_t *mxa) 119 { 120 int rc; 121 122 if (ctx->auth_level == NDR_C_AUTHN_NONE || 123 ctx->auth_type == NDR_C_AUTHN_NONE) 124 return (NDR_DRC_OK); 125 126 if (ctx->auth_type != NDR_C_AUTHN_GSS_NETLOGON) 127 return (NDR_DRC_FAULT_SEC_TYPE_UNIMPLEMENTED); 128 129 if (ctx->auth_level != NDR_C_AUTHN_LEVEL_PKT_INTEGRITY) 130 return (NDR_DRC_FAULT_SEC_LEVEL_UNIMPLEMENTED); 131 132 if ((rc = ndr_add_auth_token(ctx, mxa)) != 0) 133 return (rc); 134 135 return (ctx->auth_ops.nao_sign(ctx->auth_ctx, mxa)); 136 } 137 138 /* 139 * Does gss_VerifyMICEx (or equivalent) and validates 140 * the sec_trailer and the auth token. 141 * 142 * Used upon receiving a request (server)/response (client) packet. 143 * 144 * If auth_verify_resp is B_FALSE, this doesn't verify responses (but 145 * the SSP may still have side-effects). 146 */ 147 int 148 ndr_check_auth(ndr_auth_ctx_t *ctx, ndr_xa_t *mxa) 149 { 150 ndr_sec_t *secp = &mxa->recv_auth; 151 152 if (ctx->auth_level == NDR_C_AUTHN_NONE || 153 ctx->auth_type == NDR_C_AUTHN_NONE) { 154 if (mxa->recv_hdr.common_hdr.auth_length != 0) 155 return (NDR_DRC_FAULT_SEC_AUTH_LENGTH_INVALID); 156 return (NDR_DRC_OK); 157 } else if (mxa->recv_hdr.common_hdr.auth_length == 0) { 158 return (NDR_DRC_FAULT_SEC_AUTH_LENGTH_INVALID); 159 } 160 161 if (ctx->auth_type != secp->auth_type || 162 ctx->auth_type != NDR_C_AUTHN_GSS_NETLOGON) 163 return (NDR_DRC_FAULT_SEC_AUTH_TYPE_INVALID); 164 165 if (ctx->auth_level != secp->auth_level || 166 ctx->auth_level != NDR_C_AUTHN_LEVEL_PKT_INTEGRITY) 167 return (NDR_DRC_FAULT_SEC_AUTH_LEVEL_INVALID); 168 169 return (ctx->auth_ops.nao_verify(ctx->auth_ctx, mxa, 170 ctx->auth_verify_resp)); 171 } 172