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 <sys/md5.h> 18 #include <sys/debug.h> 19 #include <strings.h> 20 #include <stdio.h> 21 #include <smbsrv/netrauth.h> 22 #include <smbsrv/string.h> 23 #include <smbsrv/libsmb.h> 24 #include <libmlsvc.h> 25 #include <resolv.h> 26 27 /* 28 * NETLOGON SSP for "Secure RPC" works as follows: 29 * 1. The client binds to the DC without RPC-level authentication. 30 * 2. The client and server negotiate a Session Key using a client 31 * and server challenge, plus a shared secret (the machine password). 32 * This happens via NetrServerReqChallenge and NetrServerAuthenticate. 33 * The key is bound to a particular Computer/Server Name pair. 34 * 3. The client then establishes a new bind (or alters its existing one), 35 * this time requesting the NETLOGON provider for RPC-level authentication. 36 * The server uses the Computer and Domain names provided in the 37 * authentication token in the bind request in order to find 38 * the previously-negotiated Session Key (and rejects the bind if none 39 * exists). 40 * 4. The client and server then use this Session Key to provide 41 * integrity and/or confidentiality to future NETLOGON RPC messages. 42 * 43 * The functions in this file implement the NETLOGON SSP, as defined in 44 * [MS-NRPC] 3.3 "Netlogon as a Security Support Provider". 45 * 46 * Session Key negotiation is implemented in netr_auth.c. 47 * It is the same key that is used for generating NETLOGON credentials. 48 */ 49 50 enum nl_token_type { 51 NL_AUTH_REQUEST = 0x00000000, 52 NL_AUTH_RESPONSE = 0x00000001 53 }; 54 55 /* 56 * DOMAIN = domain name 57 * COMPUTER = client computer name 58 * HOST = client host name 59 * 60 * NB = NetBios format 61 * DNS = FQDN 62 * 63 * OEM = OEM_STRING 64 * COMPRESSED = Compressed UTF-8 string 65 * 66 * Each of these is NULL-terminated, and delinated by such. 67 * They are always found in this order, when specified. 68 * 69 * We currently use everything but NL_HOST_DNS_COMPRESSED_FLAG. 70 */ 71 #define NL_DOMAIN_NB_OEM_FLAG 0x00000001 72 #define NL_COMPUTER_NB_OEM_FLAG 0x00000002 73 #define NL_DOMAIN_DNS_COMPRESSED_FLAG 0x00000004 74 #define NL_HOST_DNS_COMPRESSED_FLAG 0x00000008 75 #define NL_COMPUTER_NB_COMPRESSED_FLAG 0x00000010 76 77 #define NL_DOMAIN_FLAGS \ 78 (NL_DOMAIN_NB_OEM_FLAG|NL_DOMAIN_DNS_COMPRESSED_FLAG) 79 #define NL_COMPUTER_FLAGS \ 80 (NL_COMPUTER_NB_OEM_FLAG| \ 81 NL_HOST_DNS_COMPRESSED_FLAG| \ 82 NL_COMPUTER_NB_COMPRESSED_FLAG) 83 84 #define MD_DIGEST_LEN 16 85 86 /* These structures are OPAQUE at the RPC level - not marshalled. */ 87 typedef struct nl_auth_message { 88 uint32_t nam_type; 89 uint32_t nam_flags; 90 uchar_t nam_str[1]; 91 } nl_auth_message_t; 92 93 /* 94 * The size of this structure is used for space accounting. 95 * The confounder is not present on the wire unless confidentiality 96 * has been negotiated. When generating a token, we'll adjust space accounting 97 * based on whether the confounder is present. 98 */ 99 #define NL_AUTH_CONFOUNDER_SIZE 8 100 typedef struct nl_auth_sig { 101 uint16_t nas_sig_alg; 102 uint16_t nas_seal_alg; 103 uint16_t nas_pad; 104 uint16_t nas_flags; 105 uchar_t nas_seqnum[8]; 106 uchar_t nas_sig[8]; 107 uchar_t nas_confounder[NL_AUTH_CONFOUNDER_SIZE]; /* Sealing only */ 108 } nl_auth_sig_t; 109 110 #define NL_AUTH_SIG_SIGN_SIZE 24 111 #define NL_AUTH_SIG_SEAL_SIZE 32 112 113 void 114 netr_show_msg(nl_auth_message_t *nam, ndr_stream_t *nds) 115 { 116 ndo_printf(nds, NULL, "nl_auth_message: type=0x%x flags=0x%x"); 117 } 118 119 void 120 netr_show_sig(nl_auth_sig_t *nas, ndr_stream_t *nds) 121 { 122 ndo_printf(nds, NULL, "nl_auth_sig: SignatureAlg=0x%x SealAlg=0x%x " 123 "pad=0x%x flags=0x%x SequenceNumber=%llu Signature=0x%x " 124 "Confounder=0x%x", 125 nas->nas_sig_alg, nas->nas_seal_alg, nas->nas_pad, 126 nas->nas_flags, *(uint64_t *)nas->nas_seqnum, 127 *(uint64_t *)nas->nas_sig, *(uint64_t *)nas->nas_confounder); 128 } 129 130 /* 131 * NETLOGON SSP gss_init_sec_context equivalent 132 * [MS-NRPC] 3.3.4.1.1 "Generating an Initial NL_AUTH_MESSAGE" 133 * 134 * We need to encode at least one Computer name and at least one 135 * Domain name. The server uses this to find the Session Key 136 * negotiated earlier between this client and server. 137 * 138 * We attempt to provide NL_DOMAIN_NB_OEM_FLAG, NL_COMPUTER_NB_OEM_FLAG, 139 * NL_DOMAIN_DNS_COMPRESSED_FLAG, and NL_COMPUTER_NB_COMPRESSED_FLAG. 140 * 141 * See the above comments for how these are encoded. 142 */ 143 int 144 netr_ssp_init(void *arg, ndr_xa_t *mxa) 145 { 146 netr_info_t *auth = arg; 147 ndr_common_header_t *hdr = &mxa->send_hdr.common_hdr; 148 nl_auth_message_t *nam; 149 size_t domain_len, comp_len, len; 150 int slen; 151 uchar_t *dnptrs[3], **dnlastptr; 152 153 domain_len = smb_sbequiv_strlen(auth->nb_domain); 154 comp_len = smb_sbequiv_strlen(auth->hostname); 155 156 /* 157 * Need to allocate length for two OEM_STRINGs + NULL bytes, plus space 158 * sufficient for two NULL-terminated compressed UTF-8 strings. 159 * For the UTF-8 strings, use 2*len as a heuristic. 160 */ 161 len = domain_len + 1 + comp_len + 1 + 162 strlen(auth->hostname) * 2 + strlen(auth->fqdn_domain) * 2; 163 164 hdr->auth_length = 0; 165 166 nam = NDR_MALLOC(mxa, len); 167 if (nam == NULL) 168 return (NDR_DRC_FAULT_SEC_OUT_OF_MEMORY); 169 170 nam->nam_type = NL_AUTH_REQUEST; 171 nam->nam_flags = 0; 172 173 if (domain_len != -1) { 174 slen = smb_mbstooem(nam->nam_str, auth->nb_domain, domain_len); 175 if (slen >= 0) { 176 hdr->auth_length += slen + 1; 177 nam->nam_str[hdr->auth_length - 1] = '\0'; 178 nam->nam_flags |= NL_DOMAIN_NB_OEM_FLAG; 179 } 180 } 181 182 if (comp_len != -1) { 183 slen = smb_mbstooem(nam->nam_str + hdr->auth_length, 184 auth->hostname, comp_len); 185 if (slen >= 0) { 186 hdr->auth_length += slen + 1; 187 nam->nam_str[hdr->auth_length - 1] = '\0'; 188 nam->nam_flags |= NL_COMPUTER_NB_OEM_FLAG; 189 } 190 } 191 192 dnptrs[0] = NULL; 193 dnlastptr = &dnptrs[sizeof (dnptrs) / sizeof (dnptrs[0])]; 194 195 slen = dn_comp(auth->fqdn_domain, nam->nam_str + hdr->auth_length, 196 len - hdr->auth_length, dnptrs, dnlastptr); 197 198 if (slen >= 0) { 199 hdr->auth_length += slen; 200 nam->nam_str[hdr->auth_length] = '\0'; 201 nam->nam_flags |= NL_DOMAIN_DNS_COMPRESSED_FLAG; 202 } 203 204 slen = dn_comp(auth->hostname, nam->nam_str + hdr->auth_length, 205 len - hdr->auth_length, dnptrs, dnlastptr); 206 if (slen >= 0) { 207 hdr->auth_length += slen; 208 nam->nam_str[hdr->auth_length] = '\0'; 209 nam->nam_flags |= NL_COMPUTER_NB_COMPRESSED_FLAG; 210 } 211 212 /* We must provide at least one Domain Name and Computer Name */ 213 if ((nam->nam_flags & NL_DOMAIN_FLAGS) == 0 || 214 (nam->nam_flags & NL_COMPUTER_FLAGS) == 0) 215 return (NDR_DRC_FAULT_SEC_ENCODE_FAILED); 216 217 mxa->send_auth.auth_value = (void *)nam; 218 hdr->auth_length += sizeof (nam->nam_flags) + sizeof (nam->nam_type); 219 220 return (0); 221 } 222 223 /* 224 * NETLOGON SSP response-side gss_init_sec_context equivalent 225 * [MS-NRPC] 3.3.4.1.4 "Receiving a Return NL_AUTH_MESSAGE" 226 */ 227 int 228 netr_ssp_recv(void *arg, ndr_xa_t *mxa) 229 { 230 netr_info_t *auth = arg; 231 ndr_common_header_t *ahdr = &mxa->recv_hdr.common_hdr; 232 ndr_sec_t *ack_secp = &mxa->recv_auth; 233 nl_auth_message_t *nam; 234 int rc; 235 236 nam = (nl_auth_message_t *)ack_secp->auth_value; 237 238 /* We only need to verify the length ("at least 12") and the type */ 239 if (ahdr->auth_length < 12) { 240 rc = NDR_DRC_FAULT_SEC_AUTH_LENGTH_INVALID; 241 goto errout; 242 } 243 if (nam->nam_type != NL_AUTH_RESPONSE) { 244 rc = NDR_DRC_FAULT_SEC_META_INVALID; 245 goto errout; 246 } 247 auth->clh_seqnum = 0; 248 249 return (NDR_DRC_OK); 250 251 errout: 252 netr_show_msg(nam, &mxa->recv_nds); 253 return (rc); 254 } 255 256 /* returns byte N of seqnum */ 257 #define CLS_BYTE(n, seqnum) ((seqnum >> (8 * (n))) & 0xff) 258 259 /* 260 * Perform key derivation using HMAC-MD5, as specified in MS-NRPC. 261 * This generates an intermediate key using HMAC-MD5 over zeroes using 262 * the input key, then generates the final key using HMAC-MD5 over some 263 * caller-specified data using the intermediate key. 264 * See callers for spec references (there are multiple!). 265 */ 266 int 267 netr_ssp_derive_key(uchar_t *input_key, uint_t key_len, 268 uchar_t *data, uint_t data_len, uchar_t *out_key) 269 { 270 int rc; 271 uint32_t zeroes = 0; 272 273 rc = smb_auth_hmac_md5((uchar_t *)&zeroes, 4, 274 input_key, key_len, 275 out_key); 276 277 if (rc == 0) 278 rc = smb_auth_hmac_md5(data, data_len, 279 out_key, MD_DIGEST_LEN, 280 out_key); 281 282 return (rc); 283 } 284 /* 285 * [MS-NRPC] 3.3.4.2.1 "Generating a Client Netlogon Signature Token" 286 * 287 * Set up the metadata, encrypt and increment the SequenceNumber, 288 * and sign the PDU body. If a confounder is provided, encrypt it and 289 * the PDU body. 290 * Encryption happens here because the RC4 key is derived from data 291 * generated locally for signing/verification. 292 */ 293 int 294 netr_ssp_make_token(netr_info_t *auth, ndr_stream_t *nds, nl_auth_sig_t *nas, 295 uchar_t *confounder) 296 { 297 uint32_t zeroes = 0; 298 MD5_CTX md5h; 299 BYTE local_sig[MD_DIGEST_LEN]; 300 BYTE enc_key[MD_DIGEST_LEN]; 301 uchar_t *pdu_body = nds->pdu_base_addr + nds->pdu_body_offset; 302 303 /* 304 * SignatureAlgorithm is first byte 0x77, second byte 00 for HMAC-MD5 305 * or 0x13, 0x00 for AES-HMAC-SHA256. 306 * 307 * SealAlgorithm is first byte 0x7A, second byte 00 for RC4 308 * or 0x1A, 0x00 for AES-CFB8, or 0xffff for No Sealing. 309 * 310 * Pad is always 0xffff, and flags is always 0x0000. 311 * 312 * SequenceNumber is a computed, encrypted, 64-bit number. 313 * 314 * Each of these is always encoded in little-endian order. 315 */ 316 nas->nas_sig_alg = 0x0077; 317 if (confounder != NULL) 318 nas->nas_seal_alg = 0x007A; 319 else 320 nas->nas_seal_alg = 0xffff; 321 nas->nas_pad = 0xffff; 322 nas->nas_flags = 0; 323 324 /* 325 * Calculate the SequenceNumber. 326 * Note that byte 4 gets modified, as per the spec - 327 * It's the only byte that is not just set to some other byte. 328 */ 329 nas->nas_seqnum[0] = CLS_BYTE(3, auth->clh_seqnum); 330 nas->nas_seqnum[1] = CLS_BYTE(2, auth->clh_seqnum); 331 nas->nas_seqnum[2] = CLS_BYTE(1, auth->clh_seqnum); 332 nas->nas_seqnum[3] = CLS_BYTE(0, auth->clh_seqnum); 333 nas->nas_seqnum[4] = CLS_BYTE(7, auth->clh_seqnum) | 0x80; 334 nas->nas_seqnum[5] = CLS_BYTE(6, auth->clh_seqnum); 335 nas->nas_seqnum[6] = CLS_BYTE(5, auth->clh_seqnum); 336 nas->nas_seqnum[7] = CLS_BYTE(4, auth->clh_seqnum); 337 338 auth->clh_seqnum++; 339 340 /* 341 * The HMAC-MD5 signature is computed as follows: 342 * First 8 bytes of 343 * HMAC_MD5( 344 * MD5(0x00000000 | sig_alg | seal_alg | pad | flags | 345 * <confounder if present> | PDU body), 346 * session_key) 347 */ 348 MD5Init(&md5h); 349 MD5Update(&md5h, (uchar_t *)&zeroes, 4); 350 MD5Update(&md5h, (uchar_t *)nas, 8); 351 if (confounder != NULL) 352 MD5Update(&md5h, confounder, NL_AUTH_CONFOUNDER_SIZE); 353 MD5Update(&md5h, pdu_body, nds->pdu_body_size); 354 355 MD5Final(local_sig, &md5h); 356 if (smb_auth_hmac_md5(local_sig, sizeof (local_sig), 357 auth->session_key.key, auth->session_key.len, 358 local_sig) != 0) 359 return (NDR_DRC_FAULT_SEC_SSP_FAILED); 360 361 bcopy(local_sig, nas->nas_sig, 8); 362 363 /* 364 * [MS-NRPC] 3.3.4.2.1 "Generating a Client Netlogon Signature Token" 365 * Encrypt the Confounder and PDU Body. 366 * For RC4 Encryption, the EncryptionKey is computed as follows: 367 * XorKey = (XOR each byte of session_key with 0xf0) 368 * HMAC_MD5(local_seqnum, HMAC_MD5(0x00000000, xor_key)) 369 * 370 * Step 8 says "the Confounder field and the data MUST be encrypted, 371 * in that order, using the same encryption algorithm". It also says 372 * "The server MUST initialize RC4 only once, before encrypting the 373 * Confounder field". 374 * However, that's a lie! They're encrypted independently for RC4. 375 */ 376 if (confounder != NULL) { 377 int rc; 378 379 rc = netr_ssp_derive_key( 380 auth->rpc_seal_key.key, auth->rpc_seal_key.len, 381 (uchar_t *)nas->nas_seqnum, sizeof (nas->nas_seqnum), 382 enc_key); 383 384 if (rc != 0) 385 goto errout; 386 387 if (smb_auth_RC4(nas->nas_confounder, 388 sizeof (nas->nas_confounder), 389 enc_key, sizeof (enc_key), 390 confounder, NL_AUTH_CONFOUNDER_SIZE) != 0) 391 goto errout; 392 393 if (smb_auth_RC4(pdu_body, nds->pdu_body_size, 394 enc_key, sizeof (enc_key), 395 pdu_body, nds->pdu_body_size) != 0) 396 goto errout; 397 } 398 399 /* 400 * Encrypt the SequenceNumber. 401 * For RC4 Encryption, the EncryptionKey is computed as follows: 402 * HMAC_MD5(signature, HMAC_MD5(0x00000000, session_key)) 403 */ 404 if (netr_ssp_derive_key(auth->session_key.key, auth->session_key.len, 405 (uchar_t *)nas->nas_sig, sizeof (nas->nas_sig), enc_key) != 0) 406 goto errout; 407 408 if (smb_auth_RC4(nas->nas_seqnum, sizeof (nas->nas_seqnum), 409 enc_key, sizeof (enc_key), 410 nas->nas_seqnum, sizeof (nas->nas_seqnum)) != 0) 411 goto errout; 412 413 explicit_bzero(enc_key, sizeof (enc_key)); 414 return (NDR_DRC_OK); 415 416 errout: 417 explicit_bzero(enc_key, sizeof (enc_key)); 418 return (NDR_DRC_FAULT_SEC_SSP_FAILED); 419 } 420 421 /* 422 * [MS-NRPC] 3.3.4.2.4 "Receiving a Server Netlogon Signature Token" 423 * 424 * Verify the metadata; decrypt, verify, and increment the SequenceNumber; 425 * and validate the PDU body against the provided signature. 426 * If the confounder is present, decrypt it and the PDU body. This is done here 427 * because the key relies on local_seqnum ("CopySeqNumber"), which can only be 428 * retrieved here. 429 */ 430 int 431 netr_ssp_check_token(netr_info_t *auth, ndr_stream_t *nds, nl_auth_sig_t *nas, 432 boolean_t verify_resp, boolean_t has_confounder) 433 { 434 uint32_t zeroes = 0; 435 MD5_CTX md5h; 436 BYTE local_sig[MD_DIGEST_LEN]; 437 BYTE dec_key[MD_DIGEST_LEN]; 438 BYTE local_seqnum[8]; 439 uchar_t confounder[NL_AUTH_CONFOUNDER_SIZE]; 440 uchar_t *pdu_body = nds->pdu_base_addr + nds->pdu_body_offset; 441 int rc; 442 boolean_t seqnum_bumped = B_FALSE; 443 444 /* 445 * Verify SignatureAlgorithm, SealAlgorithm, and Pad are as expected. 446 * These follow the same values as in the Client Signature. 447 */ 448 if (nas->nas_sig_alg != 0x0077 || 449 nas->nas_seal_alg != (has_confounder ? 0x007A : 0xffff) || 450 nas->nas_pad != 0xffff) { 451 rc = NDR_DRC_FAULT_SEC_META_INVALID; 452 goto errout; 453 } 454 455 /* Decrypt the SequenceNumber. This is done the same as the Client. */ 456 if (netr_ssp_derive_key(auth->session_key.key, auth->session_key.len, 457 (uchar_t *)nas->nas_sig, sizeof (nas->nas_sig), dec_key) != 0) { 458 rc = NDR_DRC_FAULT_SEC_SSP_FAILED; 459 goto errout; 460 } 461 if (smb_auth_RC4(nas->nas_seqnum, sizeof (nas->nas_seqnum), 462 dec_key, sizeof (dec_key), 463 nas->nas_seqnum, sizeof (nas->nas_seqnum)) != 0) { 464 rc = NDR_DRC_FAULT_SEC_SSP_FAILED; 465 goto errout; 466 } 467 468 /* 469 * Calculate a local version of the SequenceNumber. 470 * Note that byte 4 does NOT get modified, unlike the client. 471 */ 472 local_seqnum[0] = CLS_BYTE(3, auth->clh_seqnum); 473 local_seqnum[1] = CLS_BYTE(2, auth->clh_seqnum); 474 local_seqnum[2] = CLS_BYTE(1, auth->clh_seqnum); 475 local_seqnum[3] = CLS_BYTE(0, auth->clh_seqnum); 476 local_seqnum[4] = CLS_BYTE(7, auth->clh_seqnum); 477 local_seqnum[5] = CLS_BYTE(6, auth->clh_seqnum); 478 local_seqnum[6] = CLS_BYTE(5, auth->clh_seqnum); 479 local_seqnum[7] = CLS_BYTE(4, auth->clh_seqnum); 480 481 /* If the SequenceNumbers don't match, this is out of order - drop it */ 482 if (bcmp(local_seqnum, nas->nas_seqnum, sizeof (local_seqnum)) != 0) { 483 ndo_printf(nds, NULL, "CalculatedSeqnum: %llu " 484 "DecryptedSeqnum: %llu", 485 *(uint64_t *)local_seqnum, *(uint64_t *)nas->nas_seqnum); 486 rc = NDR_DRC_FAULT_SEC_SEQNUM_INVALID; 487 goto errout; 488 } 489 490 auth->clh_seqnum++; 491 seqnum_bumped = B_TRUE; 492 493 /* 494 * Decrypt the Confounder and PDU Body. 495 * For RC4 Encryption, the EncryptionKey is computed as follows: 496 * XorKey = (XOR each byte of session_key with 0xf0) 497 * HMAC_MD5(local_seqnum, HMAC_MD5(0x00000000, xor_key)) 498 */ 499 if (has_confounder) { 500 if (netr_ssp_derive_key( 501 auth->rpc_seal_key.key, auth->rpc_seal_key.len, 502 (uchar_t *)local_seqnum, sizeof (local_seqnum), 503 dec_key) != 0) { 504 rc = NDR_DRC_FAULT_SEC_SSP_FAILED; 505 goto errout; 506 } 507 508 if (smb_auth_RC4(confounder, NL_AUTH_CONFOUNDER_SIZE, 509 dec_key, sizeof (dec_key), 510 nas->nas_confounder, sizeof (nas->nas_confounder)) != 0) { 511 rc = NDR_DRC_FAULT_SEC_SSP_FAILED; 512 goto errout; 513 } 514 if (smb_auth_RC4(pdu_body, nds->pdu_body_size, 515 dec_key, sizeof (dec_key), 516 pdu_body, nds->pdu_body_size) != 0) { 517 rc = NDR_DRC_FAULT_SEC_SSP_FAILED; 518 goto errout; 519 } 520 } 521 522 /* 523 * Calculate the signature. 524 * This is done the same as the Client. 525 */ 526 MD5Init(&md5h); 527 MD5Update(&md5h, (uchar_t *)&zeroes, 4); 528 MD5Update(&md5h, (uchar_t *)nas, 8); 529 if (has_confounder) 530 MD5Update(&md5h, confounder, NL_AUTH_CONFOUNDER_SIZE); 531 MD5Update(&md5h, pdu_body, nds->pdu_body_size); 532 MD5Final(local_sig, &md5h); 533 if (smb_auth_hmac_md5(local_sig, sizeof (local_sig), 534 auth->session_key.key, auth->session_key.len, 535 local_sig) != 0) { 536 rc = NDR_DRC_FAULT_SEC_SSP_FAILED; 537 goto errout; 538 } 539 540 /* If the first 8 bytes don't match, drop it */ 541 if (bcmp(local_sig, nas->nas_sig, 8) != 0) { 542 ndo_printf(nds, NULL, "CalculatedSig: %llu " 543 "PacketSig: %llu", 544 *(uint64_t *)local_sig, *(uint64_t *)nas->nas_sig); 545 rc = NDR_DRC_FAULT_SEC_SIG_INVALID; 546 goto errout; 547 } 548 549 explicit_bzero(dec_key, sizeof (dec_key)); 550 return (NDR_DRC_OK); 551 552 errout: 553 netr_show_sig(nas, nds); 554 555 explicit_bzero(dec_key, sizeof (dec_key)); 556 if (!verify_resp) { 557 if (!seqnum_bumped) 558 auth->clh_seqnum++; 559 return (NDR_DRC_OK); 560 } 561 562 return (rc); 563 } 564 565 /* 566 * NETLOGON SSP gss_MICEx equivalent. 567 * Note that auth_length does NOT include the length of the confounder. 568 */ 569 int 570 netr_ssp_sign(void *arg, ndr_xa_t *mxa) 571 { 572 ndr_common_header_t *hdr = &mxa->send_hdr.common_hdr; 573 nl_auth_sig_t *nas; 574 575 hdr->auth_length = NL_AUTH_SIG_SIGN_SIZE; 576 CTASSERT(NL_AUTH_SIG_SIGN_SIZE == 577 (offsetof(nl_auth_sig_t, nas_sig) + sizeof (nas->nas_sig))); 578 nas = NDR_MALLOC(mxa, sizeof (*nas)); 579 if (nas == NULL) 580 return (NDR_DRC_FAULT_SEC_OUT_OF_MEMORY); 581 582 mxa->send_auth.auth_value = (void *)nas; 583 584 return (netr_ssp_make_token(arg, &mxa->send_nds, nas, NULL)); 585 } 586 587 /* 588 * NETLOGON SSP gss_VerifyMICEx equivalent. 589 */ 590 int 591 netr_ssp_verify(void *arg, ndr_xa_t *mxa, boolean_t verify_resp) 592 { 593 ndr_common_header_t *hdr = &mxa->recv_hdr.common_hdr; 594 ndr_sec_t *secp = &mxa->recv_auth; 595 nl_auth_sig_t *nas = (nl_auth_sig_t *)secp->auth_value; 596 597 if (hdr->auth_length < NL_AUTH_SIG_SIGN_SIZE) 598 return (NDR_DRC_FAULT_SEC_AUTH_LENGTH_INVALID); 599 600 return (netr_ssp_check_token(arg, &mxa->recv_nds, nas, verify_resp, 601 B_FALSE)); 602 } 603 604 /* 605 * NETLOGON SSP gss_WrapEx equivalent. 606 * Generate a cryptographically random confounder before signing/sealing. 607 * It is included in auth_length here. 608 */ 609 int 610 netr_ssp_encrypt(void *arg, ndr_xa_t *mxa) 611 { 612 uchar_t confounder[NL_AUTH_CONFOUNDER_SIZE]; 613 ndr_common_header_t *hdr = &mxa->send_hdr.common_hdr; 614 nl_auth_sig_t *nas; 615 616 hdr->auth_length = NL_AUTH_SIG_SEAL_SIZE; 617 CTASSERT(NL_AUTH_SIG_SEAL_SIZE == sizeof (*nas)); 618 nas = NDR_MALLOC(mxa, sizeof (*nas)); 619 if (nas == NULL) 620 return (NDR_DRC_FAULT_SEC_OUT_OF_MEMORY); 621 622 mxa->send_auth.auth_value = (void *)nas; 623 624 arc4random_buf(confounder, NL_AUTH_CONFOUNDER_SIZE); 625 return (netr_ssp_make_token(arg, &mxa->send_nds, nas, confounder)); 626 } 627 628 /* 629 * NETLOGON SSP gss_UnwrapEx equivalent. 630 * Note that the Confounder is only used for calculating the signature. 631 */ 632 int 633 netr_ssp_decrypt(void *arg, ndr_xa_t *mxa, boolean_t verify_resp) 634 { 635 ndr_common_header_t *hdr = &mxa->recv_hdr.common_hdr; 636 ndr_sec_t *secp = &mxa->recv_auth; 637 nl_auth_sig_t *nas = (nl_auth_sig_t *)secp->auth_value; 638 639 if (hdr->auth_length < NL_AUTH_SIG_SEAL_SIZE) 640 return (NDR_DRC_FAULT_SEC_AUTH_LENGTH_INVALID); 641 642 return (netr_ssp_check_token(arg, &mxa->recv_nds, nas, verify_resp, 643 B_TRUE)); 644 } 645 646 extern struct netr_info netr_global_info; 647 648 ndr_auth_ctx_t netr_ssp_ctx = { 649 .auth_ops = { 650 .nao_init = netr_ssp_init, 651 .nao_recv = netr_ssp_recv, 652 .nao_sign = netr_ssp_sign, 653 .nao_verify = netr_ssp_verify, 654 .nao_encrypt = netr_ssp_encrypt, 655 .nao_decrypt = netr_ssp_decrypt 656 }, 657 .auth_ctx = &netr_global_info, 658 .auth_context_id = 0, 659 .auth_type = NDR_C_AUTHN_GSS_NETLOGON, 660 .auth_level = NDR_C_AUTHN_LEVEL_PKT_PRIVACY, 661 .auth_verify_resp = B_TRUE 662 }; 663