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