112b65585SGordon Ross /*
212b65585SGordon Ross * CDDL HEADER START
312b65585SGordon Ross *
412b65585SGordon Ross * The contents of this file are subject to the terms of the
512b65585SGordon Ross * Common Development and Distribution License (the "License").
612b65585SGordon Ross * You may not use this file except in compliance with the License.
712b65585SGordon Ross *
812b65585SGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
912b65585SGordon Ross * or http://www.opensolaris.org/os/licensing.
1012b65585SGordon Ross * See the License for the specific language governing permissions
1112b65585SGordon Ross * and limitations under the License.
1212b65585SGordon Ross *
1312b65585SGordon Ross * When distributing Covered Code, include this CDDL HEADER in each
1412b65585SGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1512b65585SGordon Ross * If applicable, add the following below this CDDL HEADER, with the
1612b65585SGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying
1712b65585SGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner]
1812b65585SGordon Ross *
1912b65585SGordon Ross * CDDL HEADER END
2012b65585SGordon Ross */
2112b65585SGordon Ross /*
2212b65585SGordon Ross * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23e3d9e7f3SGordon Ross * Copyright 2015-2021 Tintri by DDN, Inc. All rights reserved.
242d0c20a0SMatt Barden * Copyright 2022-2023 RackTop Systems, Inc.
2512b65585SGordon Ross */
2612b65585SGordon Ross
2712b65585SGordon Ross /*
2812b65585SGordon Ross * Authentication support for SMB session setup
2912b65585SGordon Ross */
3012b65585SGordon Ross
3112b65585SGordon Ross #include <sys/types.h>
3212b65585SGordon Ross #include <sys/sid.h>
3312b65585SGordon Ross #include <sys/priv_names.h>
3412b65585SGordon Ross #include <sys/socket.h>
3512b65585SGordon Ross #include <sys/un.h>
3612b65585SGordon Ross #include <netinet/in.h>
3712b65585SGordon Ross #include <smbsrv/smb_idmap.h>
3812b65585SGordon Ross #include <smbsrv/smb_kproto.h>
3912b65585SGordon Ross #include <smbsrv/smb_token.h>
404e065a9fSAlexander Stetsenko #include <smbsrv/smb2_kproto.h>
4112b65585SGordon Ross
42b210fedeSGordon Ross static uint32_t smb_authsock_open(smb_request_t *);
4312b65585SGordon Ross static int smb_authsock_send(ksocket_t, void *, size_t);
4412b65585SGordon Ross static int smb_authsock_recv(ksocket_t, void *, size_t);
45b210fedeSGordon Ross static uint32_t smb_authsock_sendrecv(smb_request_t *, smb_lsa_msg_hdr_t *hdr,
4612b65585SGordon Ross void *sndbuf, void **recvbuf);
4712b65585SGordon Ross /* void smb_authsock_close(smb_user_t *); kproto.h */
4812b65585SGordon Ross
4912b65585SGordon Ross static uint32_t smb_auth_do_clinfo(smb_request_t *);
5012b65585SGordon Ross static uint32_t smb_auth_do_oldreq(smb_request_t *);
5112b65585SGordon Ross static uint32_t smb_auth_get_token(smb_request_t *);
5212b65585SGordon Ross static uint32_t smb_priv_xlate(smb_token_t *);
5312b65585SGordon Ross
5412b65585SGordon Ross /*
5512b65585SGordon Ross * Handle old-style session setup (non-extended security)
56811599a4SMatt Barden * Note: Used only by SMB1
5712b65585SGordon Ross *
5812b65585SGordon Ross * The user information is passed to smbd for authentication.
5912b65585SGordon Ross * If smbd can authenticate the user an access token is returned and we
6012b65585SGordon Ross * generate a cred and new user based on the token.
6112b65585SGordon Ross */
6212b65585SGordon Ross int
smb_authenticate_old(smb_request_t * sr)6312b65585SGordon Ross smb_authenticate_old(smb_request_t *sr)
6412b65585SGordon Ross {
6512b65585SGordon Ross smb_user_t *user = NULL;
6612b65585SGordon Ross uint32_t status;
6712b65585SGordon Ross
6812b65585SGordon Ross user = smb_user_new(sr->session);
6912b65585SGordon Ross if (user == NULL)
7012b65585SGordon Ross return (NT_STATUS_TOO_MANY_SESSIONS);
7112b65585SGordon Ross
7212b65585SGordon Ross /* user cleanup in smb_request_free */
7312b65585SGordon Ross sr->uid_user = user;
7412b65585SGordon Ross sr->smb_uid = user->u_uid;
75811599a4SMatt Barden sr->smb2_ssnid = 0;
7612b65585SGordon Ross
7712b65585SGordon Ross /*
7812b65585SGordon Ross * Open a connection to the local logon service.
7912b65585SGordon Ross * If we can't, it may be busy, or not running.
8012b65585SGordon Ross * Don't log here - this may be frequent.
8112b65585SGordon Ross */
82b210fedeSGordon Ross if ((status = smb_authsock_open(sr)) != 0)
8312b65585SGordon Ross goto errout;
8412b65585SGordon Ross
8512b65585SGordon Ross /*
8612b65585SGordon Ross * Tell the auth. svc who this client is.
8712b65585SGordon Ross */
8812b65585SGordon Ross if ((status = smb_auth_do_clinfo(sr)) != 0)
8912b65585SGordon Ross goto errout;
9012b65585SGordon Ross
9112b65585SGordon Ross /*
9212b65585SGordon Ross * Authentication proper
9312b65585SGordon Ross */
9412b65585SGordon Ross if ((status = smb_auth_do_oldreq(sr)) != 0)
9512b65585SGordon Ross goto errout;
9612b65585SGordon Ross
9712b65585SGordon Ross /*
9812b65585SGordon Ross * Get the final auth. token.
9912b65585SGordon Ross */
10012b65585SGordon Ross if ((status = smb_auth_get_token(sr)) != 0)
10112b65585SGordon Ross goto errout;
10212b65585SGordon Ross
10312b65585SGordon Ross return (0);
10412b65585SGordon Ross
10512b65585SGordon Ross errout:
10612b65585SGordon Ross smb_user_logoff(user);
10712b65585SGordon Ross return (status);
10812b65585SGordon Ross }
10912b65585SGordon Ross
11012b65585SGordon Ross /*
11112b65585SGordon Ross * Build an authentication request message and
11212b65585SGordon Ross * send it to the local logon service.
11312b65585SGordon Ross */
11412b65585SGordon Ross static uint32_t
smb_auth_do_oldreq(smb_request_t * sr)11512b65585SGordon Ross smb_auth_do_oldreq(smb_request_t *sr)
11612b65585SGordon Ross {
11712b65585SGordon Ross smb_lsa_msg_hdr_t msg_hdr;
11812b65585SGordon Ross smb_logon_t user_info;
11912b65585SGordon Ross XDR xdrs;
12012b65585SGordon Ross smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
12112b65585SGordon Ross void *sbuf = NULL;
12212b65585SGordon Ross void *rbuf = NULL;
12312b65585SGordon Ross uint32_t slen = 0;
12412b65585SGordon Ross uint32_t rlen = 0;
12512b65585SGordon Ross uint32_t status;
12612b65585SGordon Ross bool_t ok;
12712b65585SGordon Ross
12812b65585SGordon Ross bzero(&user_info, sizeof (smb_logon_t));
12912b65585SGordon Ross
13012b65585SGordon Ross user_info.lg_level = NETR_NETWORK_LOGON;
13112b65585SGordon Ross user_info.lg_username = sinfo->ssi_user;
13212b65585SGordon Ross user_info.lg_domain = sinfo->ssi_domain;
13312b65585SGordon Ross user_info.lg_workstation = sr->session->workstation;
13412b65585SGordon Ross user_info.lg_clnt_ipaddr = sr->session->ipaddr;
13512b65585SGordon Ross user_info.lg_local_ipaddr = sr->session->local_ipaddr;
13612b65585SGordon Ross user_info.lg_local_port = sr->session->s_local_port;
13712b65585SGordon Ross user_info.lg_challenge_key.val = sr->session->challenge_key;
13812b65585SGordon Ross user_info.lg_challenge_key.len = sr->session->challenge_len;
13912b65585SGordon Ross user_info.lg_nt_password.val = sinfo->ssi_ntpwd;
14012b65585SGordon Ross user_info.lg_nt_password.len = sinfo->ssi_ntpwlen;
14112b65585SGordon Ross user_info.lg_lm_password.val = sinfo->ssi_lmpwd;
14212b65585SGordon Ross user_info.lg_lm_password.len = sinfo->ssi_lmpwlen;
14312b65585SGordon Ross user_info.lg_native_os = sr->session->native_os;
14412b65585SGordon Ross user_info.lg_native_lm = sr->session->native_lm;
14512b65585SGordon Ross /* lg_flags? */
14612b65585SGordon Ross
14712b65585SGordon Ross slen = xdr_sizeof(smb_logon_xdr, &user_info);
14812b65585SGordon Ross sbuf = kmem_alloc(slen, KM_SLEEP);
14912b65585SGordon Ross xdrmem_create(&xdrs, sbuf, slen, XDR_ENCODE);
15012b65585SGordon Ross ok = smb_logon_xdr(&xdrs, &user_info);
15112b65585SGordon Ross xdr_destroy(&xdrs);
15212b65585SGordon Ross if (!ok) {
15312b65585SGordon Ross status = RPC_NT_BAD_STUB_DATA;
15412b65585SGordon Ross goto out;
15512b65585SGordon Ross }
15612b65585SGordon Ross
15712b65585SGordon Ross msg_hdr.lmh_msgtype = LSA_MTYPE_OLDREQ;
15812b65585SGordon Ross msg_hdr.lmh_msglen = slen;
159b210fedeSGordon Ross status = smb_authsock_sendrecv(sr, &msg_hdr, sbuf, &rbuf);
16012b65585SGordon Ross if (status != 0)
16112b65585SGordon Ross goto out;
16212b65585SGordon Ross rlen = msg_hdr.lmh_msglen;
16312b65585SGordon Ross kmem_free(sbuf, slen);
16412b65585SGordon Ross sbuf = NULL;
16512b65585SGordon Ross
16612b65585SGordon Ross /*
16712b65585SGordon Ross * Decode the response message.
16812b65585SGordon Ross */
16912b65585SGordon Ross switch (msg_hdr.lmh_msgtype) {
17012b65585SGordon Ross
17112b65585SGordon Ross case LSA_MTYPE_OK:
17212b65585SGordon Ross status = 0;
17312b65585SGordon Ross break;
17412b65585SGordon Ross
17512b65585SGordon Ross case LSA_MTYPE_ERROR:
17612b65585SGordon Ross if (rlen == sizeof (smb_lsa_eresp_t)) {
17712b65585SGordon Ross smb_lsa_eresp_t *ler = rbuf;
17812b65585SGordon Ross status = ler->ler_ntstatus;
17912b65585SGordon Ross break;
18012b65585SGordon Ross }
18112b65585SGordon Ross /* FALLTHROUGH */
18212b65585SGordon Ross
18312b65585SGordon Ross default: /* Bogus message type */
18412b65585SGordon Ross status = NT_STATUS_INTERNAL_ERROR;
18512b65585SGordon Ross break;
18612b65585SGordon Ross }
18712b65585SGordon Ross
18812b65585SGordon Ross out:
18912b65585SGordon Ross if (rbuf != NULL)
19012b65585SGordon Ross kmem_free(rbuf, rlen);
19112b65585SGordon Ross if (sbuf != NULL)
19212b65585SGordon Ross kmem_free(sbuf, slen);
19312b65585SGordon Ross
19412b65585SGordon Ross return (status);
19512b65585SGordon Ross }
19612b65585SGordon Ross
19712b65585SGordon Ross /*
19812b65585SGordon Ross * Handle new-style (extended security) session setup.
19912b65585SGordon Ross * Returns zero: success, non-zero: error (value not used)
20012b65585SGordon Ross *
20112b65585SGordon Ross * Note that this style uses a sequence of session setup requests,
20212b65585SGordon Ross * where the first has SMB UID=0, and subsequent requests in the
20312b65585SGordon Ross * same authentication sequence have the SMB UID returned for that
20412b65585SGordon Ross * first request. We allocate a USER object when the first request
20512b65585SGordon Ross * in the sequence arrives (SMB_USER_STATE_LOGGING_ON) and use that
20612b65585SGordon Ross * to maintain state between requests in this sequence. The state
20712b65585SGordon Ross * for one sequence includes an AF_UNIX "authsock" connection to the
20812b65585SGordon Ross * user-space smbd. The neat part of this is: in smbd, the handler
20912b65585SGordon Ross * for the server-side of one authsock gets only request specific to
21012b65585SGordon Ross * one authentication sequence, simplifying it's work immensely.
21112b65585SGordon Ross * When the authentication sequence is finished, with either success
21212b65585SGordon Ross * or failure, the local side of the authsock is closed.
21312b65585SGordon Ross *
21412b65585SGordon Ross * As with the old-style authentication, if we succeed, then the
21512b65585SGordon Ross * last message from smbd will be an smb_token_t encoding the
21612b65585SGordon Ross * information about the new user.
21712b65585SGordon Ross *
21812b65585SGordon Ross * Outline:
21912b65585SGordon Ross * (a) On the first request (UID==0) create a USER object,
22012b65585SGordon Ross * and on subsequent requests, find USER by SMB UID.
22112b65585SGordon Ross * (b) Send message / recv. response as above,
22212b65585SGordon Ross * (c) If response says "we're done", close authsock
22312b65585SGordon Ross * (both success and failure must close authsock)
22412b65585SGordon Ross */
22512b65585SGordon Ross int
smb_authenticate_ext(smb_request_t * sr)22612b65585SGordon Ross smb_authenticate_ext(smb_request_t *sr)
22712b65585SGordon Ross {
22812b65585SGordon Ross smb_lsa_msg_hdr_t msg_hdr;
22912b65585SGordon Ross smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
23012b65585SGordon Ross smb_user_t *user = NULL;
23112b65585SGordon Ross void *rbuf = NULL;
23212b65585SGordon Ross uint32_t rlen = 0;
23312b65585SGordon Ross uint32_t status;
23412b65585SGordon Ross
23512b65585SGordon Ross ASSERT(sr->uid_user == NULL);
23612b65585SGordon Ross
23712b65585SGordon Ross /*
238811599a4SMatt Barden * Paranoid: While finding/creating the user object, make sure
239811599a4SMatt Barden * SMB2 ignores smb_uid, and SMB1 ignores smb2_ssnid. The
240811599a4SMatt Barden * logic below assumes the "other" one is always zero; both
241811599a4SMatt Barden * the "first request" tests and smb_session_lookup_uid_st.
242811599a4SMatt Barden */
243811599a4SMatt Barden if (sr->session->dialect >= SMB_VERS_2_BASE) {
244811599a4SMatt Barden /* SMB2+ ignores smb_uid */
245811599a4SMatt Barden ASSERT(sr->smb_uid == 0);
246811599a4SMatt Barden sr->smb_uid = 0;
247811599a4SMatt Barden } else {
248811599a4SMatt Barden /* SMB1 ignores smb2_ssnid */
249811599a4SMatt Barden ASSERT(sr->smb2_ssnid == 0);
250811599a4SMatt Barden sr->smb2_ssnid = 0;
251811599a4SMatt Barden }
252811599a4SMatt Barden
253811599a4SMatt Barden /*
254811599a4SMatt Barden * On the first request (UID/ssnid==0) create a USER object.
255811599a4SMatt Barden * On subsequent requests (UID/ssnid!=0) find the USER object.
25612b65585SGordon Ross * Either way, sr->uid_user is set, so our ref. on the
25712b65585SGordon Ross * user object is dropped during normal cleanup work
25812b65585SGordon Ross * for the smb_request (sr). Ditto u_authsock.
25912b65585SGordon Ross */
260811599a4SMatt Barden if (sr->smb2_ssnid == 0 && sr->smb_uid == 0) {
26112b65585SGordon Ross user = smb_user_new(sr->session);
26212b65585SGordon Ross if (user == NULL)
26312b65585SGordon Ross return (NT_STATUS_TOO_MANY_SESSIONS);
26412b65585SGordon Ross
26512b65585SGordon Ross /* user cleanup in smb_request_free */
26612b65585SGordon Ross sr->uid_user = user;
267811599a4SMatt Barden if (sr->session->dialect >= SMB_VERS_2_BASE) {
268811599a4SMatt Barden /* Intentionally leave smb_uid=0 for SMB2 */
269811599a4SMatt Barden sr->smb2_ssnid = user->u_ssnid;
270811599a4SMatt Barden } else {
271811599a4SMatt Barden /* Intentionally leave smb2_ssnid=0 for SMB1 */
272811599a4SMatt Barden sr->smb_uid = user->u_uid;
273811599a4SMatt Barden }
27412b65585SGordon Ross
27512b65585SGordon Ross /*
27612b65585SGordon Ross * Open a connection to the local logon service.
27712b65585SGordon Ross * If we can't, it may be busy, or not running.
27812b65585SGordon Ross * Don't log here - this may be frequent.
27912b65585SGordon Ross */
280b210fedeSGordon Ross if ((status = smb_authsock_open(sr)) != 0)
28112b65585SGordon Ross goto errout;
28212b65585SGordon Ross
28312b65585SGordon Ross /*
28412b65585SGordon Ross * Tell the auth. svc who this client is.
28512b65585SGordon Ross */
28612b65585SGordon Ross if ((status = smb_auth_do_clinfo(sr)) != 0)
28712b65585SGordon Ross goto errout;
28812b65585SGordon Ross
28912b65585SGordon Ross msg_hdr.lmh_msgtype = LSA_MTYPE_ESFIRST;
2904e065a9fSAlexander Stetsenko
2914e065a9fSAlexander Stetsenko if (sr->session->dialect >= SMB_VERS_3_11) {
2924e065a9fSAlexander Stetsenko if (smb31_preauth_sha512_calc(sr, &sr->command,
2934e065a9fSAlexander Stetsenko sr->session->smb31_preauth_hashval,
2944e065a9fSAlexander Stetsenko user->u_preauth_hashval) != 0)
2954e065a9fSAlexander Stetsenko cmn_err(CE_WARN, "(2) Preauth hash calculation "
2964e065a9fSAlexander Stetsenko "failed");
2974e065a9fSAlexander Stetsenko }
29812b65585SGordon Ross } else {
29912b65585SGordon Ross user = smb_session_lookup_uid_st(sr->session,
300811599a4SMatt Barden sr->smb2_ssnid, sr->smb_uid, SMB_USER_STATE_LOGGING_ON);
30112b65585SGordon Ross if (user == NULL)
30212b65585SGordon Ross return (NT_STATUS_USER_SESSION_DELETED);
30312b65585SGordon Ross
30412b65585SGordon Ross /* user cleanup in smb_request_free */
30512b65585SGordon Ross sr->uid_user = user;
30612b65585SGordon Ross
30712b65585SGordon Ross msg_hdr.lmh_msgtype = LSA_MTYPE_ESNEXT;
3084e065a9fSAlexander Stetsenko
3094e065a9fSAlexander Stetsenko if (sr->session->dialect >= SMB_VERS_3_11) {
3104e065a9fSAlexander Stetsenko if (smb31_preauth_sha512_calc(sr, &sr->command,
3114e065a9fSAlexander Stetsenko user->u_preauth_hashval,
3124e065a9fSAlexander Stetsenko user->u_preauth_hashval) != 0)
3134e065a9fSAlexander Stetsenko cmn_err(CE_WARN, "(4) Preauth hash calculation "
3144e065a9fSAlexander Stetsenko "failed");
3154e065a9fSAlexander Stetsenko }
31612b65585SGordon Ross }
31712b65585SGordon Ross
31812b65585SGordon Ross /*
31912b65585SGordon Ross * Wrap the "security blob" with our header
32012b65585SGordon Ross * (LSA_MTYPE_ESFIRST or LSA_MTYPE_ESNEXT)
32112b65585SGordon Ross * and send it up the authsock with either
32212b65585SGordon Ross */
32312b65585SGordon Ross msg_hdr.lmh_msglen = sinfo->ssi_iseclen;
324b210fedeSGordon Ross status = smb_authsock_sendrecv(sr, &msg_hdr,
32512b65585SGordon Ross sinfo->ssi_isecblob, &rbuf);
32612b65585SGordon Ross if (status != 0)
32712b65585SGordon Ross goto errout;
32812b65585SGordon Ross rlen = msg_hdr.lmh_msglen;
32912b65585SGordon Ross
33012b65585SGordon Ross /*
33112b65585SGordon Ross * Decode the response message.
33212b65585SGordon Ross * Note: allocated rbuf
33312b65585SGordon Ross */
33412b65585SGordon Ross switch (msg_hdr.lmh_msgtype) {
33512b65585SGordon Ross
33612b65585SGordon Ross case LSA_MTYPE_ES_CONT:
33712b65585SGordon Ross sinfo->ssi_oseclen = (uint16_t)rlen;
33812b65585SGordon Ross sinfo->ssi_osecblob = smb_srm_alloc(sr, sinfo->ssi_oseclen);
33912b65585SGordon Ross bcopy(rbuf, sinfo->ssi_osecblob, sinfo->ssi_oseclen);
34012b65585SGordon Ross /*
34112b65585SGordon Ross * This is not really an error, but tells the client
34212b65585SGordon Ross * it should send another session setup request.
34312b65585SGordon Ross */
34412b65585SGordon Ross status = NT_STATUS_MORE_PROCESSING_REQUIRED;
34512b65585SGordon Ross break;
34612b65585SGordon Ross
34712b65585SGordon Ross case LSA_MTYPE_ES_DONE:
34812b65585SGordon Ross sinfo->ssi_oseclen = (uint16_t)rlen;
34912b65585SGordon Ross sinfo->ssi_osecblob = smb_srm_alloc(sr, sinfo->ssi_oseclen);
35012b65585SGordon Ross bcopy(rbuf, sinfo->ssi_osecblob, sinfo->ssi_oseclen);
35112b65585SGordon Ross sinfo->ssi_ntpwlen = 0;
35212b65585SGordon Ross /*
35312b65585SGordon Ross * Get the final auth. token.
35412b65585SGordon Ross */
35512b65585SGordon Ross status = smb_auth_get_token(sr);
35612b65585SGordon Ross break;
35712b65585SGordon Ross
35812b65585SGordon Ross case LSA_MTYPE_ERROR:
35912b65585SGordon Ross /*
36012b65585SGordon Ross * Authentication failed. Return the error
36112b65585SGordon Ross * provided in the reply message.
36212b65585SGordon Ross */
36312b65585SGordon Ross if (rlen == sizeof (smb_lsa_eresp_t)) {
36412b65585SGordon Ross smb_lsa_eresp_t *ler = rbuf;
36512b65585SGordon Ross status = ler->ler_ntstatus;
36612b65585SGordon Ross goto errout;
36712b65585SGordon Ross }
36812b65585SGordon Ross /* FALLTHROUGH */
36912b65585SGordon Ross
37012b65585SGordon Ross default: /* Bogus message type */
37112b65585SGordon Ross status = NT_STATUS_INTERNAL_ERROR;
37212b65585SGordon Ross goto errout;
37312b65585SGordon Ross }
37412b65585SGordon Ross
37512b65585SGordon Ross if (status != 0 && status != NT_STATUS_MORE_PROCESSING_REQUIRED) {
37612b65585SGordon Ross errout:
37712b65585SGordon Ross smb_user_logoff(user);
37812b65585SGordon Ross }
37912b65585SGordon Ross
38012b65585SGordon Ross if (rbuf != NULL)
38112b65585SGordon Ross kmem_free(rbuf, rlen);
38212b65585SGordon Ross
38312b65585SGordon Ross return (status);
38412b65585SGordon Ross }
38512b65585SGordon Ross
38612b65585SGordon Ross /*
38712b65585SGordon Ross * Send the "client info" up to the auth service.
38812b65585SGordon Ross */
38912b65585SGordon Ross static uint32_t
smb_auth_do_clinfo(smb_request_t * sr)39012b65585SGordon Ross smb_auth_do_clinfo(smb_request_t *sr)
39112b65585SGordon Ross {
39212b65585SGordon Ross smb_lsa_msg_hdr_t msg_hdr;
39312b65585SGordon Ross smb_lsa_clinfo_t clinfo;
39412b65585SGordon Ross void *rbuf = NULL;
39512b65585SGordon Ross uint32_t status;
39612b65585SGordon Ross
39712b65585SGordon Ross /*
39812b65585SGordon Ross * Send a message with info. about the client
39912b65585SGordon Ross * (IP address, etc) and wait for an ACK.
40012b65585SGordon Ross */
40112b65585SGordon Ross msg_hdr.lmh_msgtype = LSA_MTYPE_CLINFO;
40212b65585SGordon Ross msg_hdr.lmh_msglen = sizeof (clinfo);
40312b65585SGordon Ross clinfo.lci_clnt_ipaddr = sr->session->ipaddr;
40412b65585SGordon Ross (void) memcpy(clinfo.lci_challenge_key,
40512b65585SGordon Ross sr->session->challenge_key,
40612b65585SGordon Ross sizeof (clinfo.lci_challenge_key));
407b210fedeSGordon Ross status = smb_authsock_sendrecv(sr, &msg_hdr, &clinfo, &rbuf);
40812b65585SGordon Ross /* We don't use this response. */
40912b65585SGordon Ross if (rbuf != NULL) {
41012b65585SGordon Ross kmem_free(rbuf, msg_hdr.lmh_msglen);
41112b65585SGordon Ross rbuf = NULL;
41212b65585SGordon Ross }
41312b65585SGordon Ross
41412b65585SGordon Ross return (status);
41512b65585SGordon Ross }
41612b65585SGordon Ross
41712b65585SGordon Ross /*
41812b65585SGordon Ross * After a successful authentication, ask the authsvc to
41912b65585SGordon Ross * send us the authentication token.
42012b65585SGordon Ross */
42112b65585SGordon Ross static uint32_t
smb_auth_get_token(smb_request_t * sr)42212b65585SGordon Ross smb_auth_get_token(smb_request_t *sr)
42312b65585SGordon Ross {
42412b65585SGordon Ross smb_lsa_msg_hdr_t msg_hdr;
42512b65585SGordon Ross XDR xdrs;
42612b65585SGordon Ross smb_user_t *user = sr->uid_user;
42712b65585SGordon Ross smb_token_t *token = NULL;
42812b65585SGordon Ross cred_t *cr = NULL;
42912b65585SGordon Ross void *rbuf = NULL;
43012b65585SGordon Ross uint32_t rlen = 0;
43112b65585SGordon Ross uint32_t privileges;
43212b65585SGordon Ross uint32_t status;
43312b65585SGordon Ross bool_t ok;
43412b65585SGordon Ross
43512b65585SGordon Ross msg_hdr.lmh_msgtype = LSA_MTYPE_GETTOK;
43612b65585SGordon Ross msg_hdr.lmh_msglen = 0;
43712b65585SGordon Ross
438b210fedeSGordon Ross status = smb_authsock_sendrecv(sr, &msg_hdr, NULL, &rbuf);
43912b65585SGordon Ross if (status != 0)
44012b65585SGordon Ross goto errout;
44112b65585SGordon Ross
44212b65585SGordon Ross rlen = msg_hdr.lmh_msglen;
44312b65585SGordon Ross switch (msg_hdr.lmh_msgtype) {
44412b65585SGordon Ross
44512b65585SGordon Ross case LSA_MTYPE_TOKEN:
44612b65585SGordon Ross status = 0;
44712b65585SGordon Ross break;
44812b65585SGordon Ross
44912b65585SGordon Ross case LSA_MTYPE_ERROR:
45012b65585SGordon Ross if (rlen == sizeof (smb_lsa_eresp_t)) {
45112b65585SGordon Ross smb_lsa_eresp_t *ler = rbuf;
45212b65585SGordon Ross status = ler->ler_ntstatus;
45312b65585SGordon Ross goto errout;
45412b65585SGordon Ross }
45512b65585SGordon Ross /* FALLTHROUGH */
45612b65585SGordon Ross
45712b65585SGordon Ross default:
45812b65585SGordon Ross status = NT_STATUS_INTERNAL_ERROR;
45912b65585SGordon Ross goto errout;
46012b65585SGordon Ross }
46112b65585SGordon Ross
46212b65585SGordon Ross /*
46312b65585SGordon Ross * Authenticated. Decode the LSA_MTYPE_TOKEN.
46412b65585SGordon Ross */
46512b65585SGordon Ross xdrmem_create(&xdrs, rbuf, rlen, XDR_DECODE);
46612b65585SGordon Ross token = kmem_zalloc(sizeof (smb_token_t), KM_SLEEP);
46712b65585SGordon Ross ok = smb_token_xdr(&xdrs, token);
46812b65585SGordon Ross xdr_destroy(&xdrs);
46912b65585SGordon Ross if (!ok) {
47012b65585SGordon Ross status = RPC_NT_BAD_STUB_DATA;
47112b65585SGordon Ross goto errout;
47212b65585SGordon Ross }
47312b65585SGordon Ross kmem_free(rbuf, rlen);
47412b65585SGordon Ross rbuf = NULL;
47512b65585SGordon Ross
47612b65585SGordon Ross /*
47712b65585SGordon Ross * Setup the logon object.
47812b65585SGordon Ross */
47912b65585SGordon Ross cr = smb_cred_create(token);
480e3d9e7f3SGordon Ross if (cr == NULL) {
481e3d9e7f3SGordon Ross status = NT_STATUS_INTERNAL_ERROR;
48212b65585SGordon Ross goto errout;
483e3d9e7f3SGordon Ross }
48412b65585SGordon Ross privileges = smb_priv_xlate(token);
48512b65585SGordon Ross (void) smb_user_logon(user, cr,
48612b65585SGordon Ross token->tkn_domain_name, token->tkn_account_name,
48712b65585SGordon Ross token->tkn_flags, privileges, token->tkn_audit_sid);
48812b65585SGordon Ross crfree(cr);
48912b65585SGordon Ross
4901160dcf7SMatt Barden /*
4912d0c20a0SMatt Barden * Set Session.EncryptData so encryption can be enforced,
4922d0c20a0SMatt Barden * and set up encryption keys if we have a session key.
4932d0c20a0SMatt Barden * This happens even for anonymous/guest users, as Windows
4942d0c20a0SMatt Barden * currently will send encrypted requests from them.
4951160dcf7SMatt Barden */
4961160dcf7SMatt Barden if (sr->session->dialect >= SMB_VERS_3_0)
4974f0ce1daSGordon Ross smb3_encrypt_begin(sr->uid_user, token);
4981160dcf7SMatt Barden
49912b65585SGordon Ross /*
50012b65585SGordon Ross * Save the session key, and (maybe) enable signing,
50112b65585SGordon Ross * but only for real logon (not ANON or GUEST).
50212b65585SGordon Ross */
50312b65585SGordon Ross if ((token->tkn_flags & (SMB_ATF_GUEST | SMB_ATF_ANON)) == 0) {
504a90cf9f2SGordon Ross if (sr->session->dialect >= SMB_VERS_2_BASE) {
505c51c88bdSMatt Barden smb2_sign_begin(sr, token);
506a90cf9f2SGordon Ross } else {
507c51c88bdSMatt Barden smb_sign_begin(sr, token);
50812b65585SGordon Ross }
50912b65585SGordon Ross }
51012b65585SGordon Ross
51112b65585SGordon Ross smb_token_free(token);
51212b65585SGordon Ross
51312b65585SGordon Ross sr->user_cr = user->u_cred;
51412b65585SGordon Ross return (0);
51512b65585SGordon Ross
51612b65585SGordon Ross errout:
51712b65585SGordon Ross if (rbuf != NULL)
51812b65585SGordon Ross kmem_free(rbuf, rlen);
51912b65585SGordon Ross if (token != NULL)
52012b65585SGordon Ross smb_token_free(token);
52112b65585SGordon Ross return (status);
52212b65585SGordon Ross }
52312b65585SGordon Ross
52412b65585SGordon Ross /*
52512b65585SGordon Ross * Tokens are allocated in the kernel via XDR.
52612b65585SGordon Ross * Call xdr_free before freeing the token structure.
52712b65585SGordon Ross */
52812b65585SGordon Ross void
smb_token_free(smb_token_t * token)52912b65585SGordon Ross smb_token_free(smb_token_t *token)
53012b65585SGordon Ross {
53112b65585SGordon Ross if (token != NULL) {
53212b65585SGordon Ross xdr_free(smb_token_xdr, (char *)token);
53312b65585SGordon Ross kmem_free(token, sizeof (smb_token_t));
53412b65585SGordon Ross }
53512b65585SGordon Ross }
53612b65585SGordon Ross
53712b65585SGordon Ross /*
53812b65585SGordon Ross * Convert access token privileges to local definitions.
53912b65585SGordon Ross */
54012b65585SGordon Ross static uint32_t
smb_priv_xlate(smb_token_t * token)54112b65585SGordon Ross smb_priv_xlate(smb_token_t *token)
54212b65585SGordon Ross {
54312b65585SGordon Ross uint32_t privileges = 0;
54412b65585SGordon Ross
545cc3780e6SGordon Ross if (smb_token_query_privilege(token, SE_SECURITY_LUID))
546cc3780e6SGordon Ross privileges |= SMB_USER_PRIV_SECURITY;
547cc3780e6SGordon Ross
548cc3780e6SGordon Ross if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID))
549cc3780e6SGordon Ross privileges |= SMB_USER_PRIV_TAKE_OWNERSHIP;
550cc3780e6SGordon Ross
55112b65585SGordon Ross if (smb_token_query_privilege(token, SE_BACKUP_LUID))
55212b65585SGordon Ross privileges |= SMB_USER_PRIV_BACKUP;
55312b65585SGordon Ross
55412b65585SGordon Ross if (smb_token_query_privilege(token, SE_RESTORE_LUID))
55512b65585SGordon Ross privileges |= SMB_USER_PRIV_RESTORE;
55612b65585SGordon Ross
557cc3780e6SGordon Ross if (smb_token_query_privilege(token, SE_CHANGE_NOTIFY_LUID))
558cc3780e6SGordon Ross privileges |= SMB_USER_PRIV_CHANGE_NOTIFY;
55912b65585SGordon Ross
5600292c176SMatt Barden if (smb_token_query_privilege(token, SE_READ_FILE_LUID))
5610292c176SMatt Barden privileges |= SMB_USER_PRIV_READ_FILE;
5620292c176SMatt Barden
5630292c176SMatt Barden if (smb_token_query_privilege(token, SE_WRITE_FILE_LUID))
5640292c176SMatt Barden privileges |= SMB_USER_PRIV_WRITE_FILE;
5650292c176SMatt Barden
56612b65585SGordon Ross return (privileges);
56712b65585SGordon Ross }
56812b65585SGordon Ross
569b210fedeSGordon Ross /*
570b210fedeSGordon Ross * Unblock a request that might be blocked reading some
571b210fedeSGordon Ross * authentication socket. This can happen when either the
572b210fedeSGordon Ross * client cancels a session setup or closes the connection.
573b210fedeSGordon Ross */
574b210fedeSGordon Ross static void
smb_authsock_cancel(smb_request_t * sr)575b210fedeSGordon Ross smb_authsock_cancel(smb_request_t *sr)
576b210fedeSGordon Ross {
577b210fedeSGordon Ross smb_user_t *user = sr->cancel_arg2;
578b210fedeSGordon Ross ksocket_t authsock = NULL;
579b210fedeSGordon Ross
580b210fedeSGordon Ross ASSERT(user == sr->uid_user);
581b210fedeSGordon Ross
582b210fedeSGordon Ross /*
583b210fedeSGordon Ross * Check user state, and get a hold on the auth socket.
584b210fedeSGordon Ross */
585b210fedeSGordon Ross mutex_enter(&user->u_mutex);
586b210fedeSGordon Ross if (user->u_state == SMB_USER_STATE_LOGGING_ON) {
587b210fedeSGordon Ross if ((authsock = user->u_authsock) != NULL)
588b210fedeSGordon Ross ksocket_hold(authsock);
589b210fedeSGordon Ross }
590b210fedeSGordon Ross mutex_exit(&user->u_mutex);
591b210fedeSGordon Ross
592b210fedeSGordon Ross if (authsock != NULL) {
593b210fedeSGordon Ross (void) ksocket_shutdown(authsock, SHUT_RDWR, sr->user_cr);
594b210fedeSGordon Ross ksocket_rele(authsock);
595b210fedeSGordon Ross }
596b210fedeSGordon Ross }
597b210fedeSGordon Ross
59812b65585SGordon Ross /*
59912b65585SGordon Ross * Send/recv a request/reply sequence on the auth socket.
60012b65585SGordon Ross * Returns zero or an NT status.
60112b65585SGordon Ross *
60212b65585SGordon Ross * Errors here mean we can't communicate with the smbd_authsvc.
60312b65585SGordon Ross * With limited authsock instances, this should be rare.
60412b65585SGordon Ross */
60512b65585SGordon Ross static uint32_t
smb_authsock_sendrecv(smb_request_t * sr,smb_lsa_msg_hdr_t * hdr,void * sndbuf,void ** recvbuf)606b210fedeSGordon Ross smb_authsock_sendrecv(smb_request_t *sr, smb_lsa_msg_hdr_t *hdr,
6071160dcf7SMatt Barden void *sndbuf, void **recvbuf)
60812b65585SGordon Ross {
609b210fedeSGordon Ross smb_user_t *user = sr->uid_user;
61012b65585SGordon Ross ksocket_t so;
61112b65585SGordon Ross uint32_t status;
61212b65585SGordon Ross int rc;
61312b65585SGordon Ross
61412b65585SGordon Ross /*
61512b65585SGordon Ross * Get a hold on the auth socket.
61612b65585SGordon Ross */
61712b65585SGordon Ross mutex_enter(&user->u_mutex);
61812b65585SGordon Ross so = user->u_authsock;
61912b65585SGordon Ross if (so == NULL) {
62012b65585SGordon Ross mutex_exit(&user->u_mutex);
62112b65585SGordon Ross return (NT_STATUS_INTERNAL_ERROR);
62212b65585SGordon Ross }
62312b65585SGordon Ross ksocket_hold(so);
62412b65585SGordon Ross mutex_exit(&user->u_mutex);
62512b65585SGordon Ross
626*66b505f1SGordon Ross /*
627*66b505f1SGordon Ross * Prepare for cancellable send/recv.
628*66b505f1SGordon Ross */
629b210fedeSGordon Ross mutex_enter(&sr->sr_mutex);
630b210fedeSGordon Ross if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
631b210fedeSGordon Ross mutex_exit(&sr->sr_mutex);
632b210fedeSGordon Ross status = NT_STATUS_CANCELLED;
633b210fedeSGordon Ross goto out;
634b210fedeSGordon Ross }
635b210fedeSGordon Ross sr->sr_state = SMB_REQ_STATE_WAITING_AUTH;
636b210fedeSGordon Ross sr->cancel_method = smb_authsock_cancel;
637b210fedeSGordon Ross sr->cancel_arg2 = user;
638b210fedeSGordon Ross mutex_exit(&sr->sr_mutex);
639b210fedeSGordon Ross
640*66b505f1SGordon Ross /*
641*66b505f1SGordon Ross * The actual send/recv work.
642*66b505f1SGordon Ross */
64312b65585SGordon Ross rc = smb_authsock_send(so, hdr, sizeof (*hdr));
64412b65585SGordon Ross if (rc == 0 && hdr->lmh_msglen != 0) {
64512b65585SGordon Ross rc = smb_authsock_send(so, sndbuf, hdr->lmh_msglen);
64612b65585SGordon Ross }
647b210fedeSGordon Ross if (rc == 0)
648b210fedeSGordon Ross rc = smb_authsock_recv(so, hdr, sizeof (*hdr));
64912b65585SGordon Ross if (rc == 0 && hdr->lmh_msglen != 0) {
65012b65585SGordon Ross *recvbuf = kmem_alloc(hdr->lmh_msglen, KM_SLEEP);
65112b65585SGordon Ross rc = smb_authsock_recv(so, *recvbuf, hdr->lmh_msglen);
65212b65585SGordon Ross }
65312b65585SGordon Ross
65412b65585SGordon Ross switch (rc) {
65512b65585SGordon Ross case 0:
65612b65585SGordon Ross status = 0;
65712b65585SGordon Ross break;
65812b65585SGordon Ross case EIO:
65912b65585SGordon Ross status = RPC_NT_COMM_FAILURE;
66012b65585SGordon Ross break;
66112b65585SGordon Ross case ENOTCONN:
66212b65585SGordon Ross status = RPC_NT_PIPE_CLOSED;
66312b65585SGordon Ross break;
66412b65585SGordon Ross default:
66512b65585SGordon Ross status = RPC_NT_CALL_FAILED;
66612b65585SGordon Ross break;
66712b65585SGordon Ross }
66812b65585SGordon Ross
669*66b505f1SGordon Ross /*
670*66b505f1SGordon Ross * Did send/recv complete or was it cancelled?
671*66b505f1SGordon Ross */
672b210fedeSGordon Ross mutex_enter(&sr->sr_mutex);
673*66b505f1SGordon Ross switch_state:
674b210fedeSGordon Ross switch (sr->sr_state) {
675b210fedeSGordon Ross case SMB_REQ_STATE_WAITING_AUTH:
676*66b505f1SGordon Ross /* Normal wakeup. Keep status from above. */
677b210fedeSGordon Ross sr->sr_state = SMB_REQ_STATE_ACTIVE;
678b210fedeSGordon Ross break;
679b210fedeSGordon Ross case SMB_REQ_STATE_CANCEL_PENDING:
680*66b505f1SGordon Ross /* cancel_method running. wait. */
681*66b505f1SGordon Ross cv_wait(&sr->sr_st_cv, &sr->sr_mutex);
682*66b505f1SGordon Ross goto switch_state;
683*66b505f1SGordon Ross case SMB_REQ_STATE_CANCELLED:
684b210fedeSGordon Ross status = NT_STATUS_CANCELLED;
685b210fedeSGordon Ross break;
686b210fedeSGordon Ross default:
687b210fedeSGordon Ross status = NT_STATUS_INTERNAL_ERROR;
688b210fedeSGordon Ross break;
689b210fedeSGordon Ross }
690*66b505f1SGordon Ross sr->cancel_method = NULL;
691*66b505f1SGordon Ross sr->cancel_arg2 = NULL;
692b210fedeSGordon Ross mutex_exit(&sr->sr_mutex);
693b210fedeSGordon Ross
694b210fedeSGordon Ross out:
695b210fedeSGordon Ross ksocket_rele(so);
696b210fedeSGordon Ross
697b210fedeSGordon Ross if (status != 0 && *recvbuf != NULL) {
698b210fedeSGordon Ross kmem_free(*recvbuf, hdr->lmh_msglen);
699b210fedeSGordon Ross *recvbuf = NULL;
700b210fedeSGordon Ross }
70112b65585SGordon Ross return (status);
70212b65585SGordon Ross }
70312b65585SGordon Ross
70412b65585SGordon Ross /*
70512b65585SGordon Ross * Hope this is interpreted per-zone...
70612b65585SGordon Ross */
70712b65585SGordon Ross static struct sockaddr_un smbauth_sockname = {
70812b65585SGordon Ross AF_UNIX, SMB_AUTHSVC_SOCKNAME };
70912b65585SGordon Ross
71012b65585SGordon Ross /*
71112b65585SGordon Ross * Limit how long smb_authsock_sendrecv() will wait for a
71212b65585SGordon Ross * response from the local authentication service.
71312b65585SGordon Ross */
71412b65585SGordon Ross struct timeval smb_auth_recv_tmo = { 45, 0 };
71512b65585SGordon Ross
71612b65585SGordon Ross /*
71712b65585SGordon Ross * Also limit the time smb_authsock_sendrecv() will wait
71812b65585SGordon Ross * trying to send a request to the authentication service.
71912b65585SGordon Ross */
72012b65585SGordon Ross struct timeval smb_auth_send_tmo = { 15, 0 };
72112b65585SGordon Ross
7228f70e16bSGordon Ross /*
7238f70e16bSGordon Ross * Maximum time a user object may stay in state LOGGING_ON
7248f70e16bSGordon Ross */
7258f70e16bSGordon Ross int smb_auth_total_tmo = 45; /* seconds */
7268f70e16bSGordon Ross
72712b65585SGordon Ross static uint32_t
smb_authsock_open(smb_request_t * sr)728b210fedeSGordon Ross smb_authsock_open(smb_request_t *sr)
72912b65585SGordon Ross {
730b210fedeSGordon Ross smb_user_t *user = sr->uid_user;
731b210fedeSGordon Ross smb_server_t *sv = sr->sr_server;
73212b65585SGordon Ross ksocket_t so = NULL;
733b210fedeSGordon Ross uint32_t status = 0;
73412b65585SGordon Ross int rc;
73512b65585SGordon Ross
73612b65585SGordon Ross /*
737b210fedeSGordon Ross * If the auth. service is busy, wait our turn. This threshold
738b210fedeSGordon Ross * limits the number of auth sockets we might have trying to
739b210fedeSGordon Ross * communicate with the auth. service up in smbd. Until we've
740b210fedeSGordon Ross * set u_authsock, we need to "exit this threshold" in any
741b210fedeSGordon Ross * error code paths after this "enter".
742b210fedeSGordon Ross *
743b210fedeSGordon Ross * Failure to "enter" may be frequent, so don't log.
74412b65585SGordon Ross */
74512b65585SGordon Ross if ((rc = smb_threshold_enter(&sv->sv_ssetup_ct)) != 0)
74612b65585SGordon Ross return (NT_STATUS_NO_LOGON_SERVERS);
74712b65585SGordon Ross
74812b65585SGordon Ross rc = ksocket_socket(&so, AF_UNIX, SOCK_STREAM, 0,
74912b65585SGordon Ross KSOCKET_SLEEP, CRED());
75012b65585SGordon Ross if (rc != 0) {
75112b65585SGordon Ross cmn_err(CE_NOTE, "smb_authsock_open: socket, rc=%d", rc);
752b210fedeSGordon Ross smb_threshold_exit(&sv->sv_ssetup_ct);
75312b65585SGordon Ross status = NT_STATUS_INSUFF_SERVER_RESOURCES;
75412b65585SGordon Ross goto errout;
75512b65585SGordon Ross }
75612b65585SGordon Ross
757b210fedeSGordon Ross /*
758b210fedeSGordon Ross * This (new) user object now gets an authsocket.
759b210fedeSGordon Ross * Note: u_authsock cleanup in smb_user_logoff.
760b210fedeSGordon Ross * After we've set u_authsock, smb_threshold_exit
7618f70e16bSGordon Ross * is done in smb_authsock_close(). If we somehow
7628f70e16bSGordon Ross * already have an authsock, close the new one and
7638f70e16bSGordon Ross * error out.
764b210fedeSGordon Ross */
765b210fedeSGordon Ross mutex_enter(&user->u_mutex);
766b210fedeSGordon Ross if (user->u_authsock != NULL) {
767b210fedeSGordon Ross mutex_exit(&user->u_mutex);
7688f70e16bSGordon Ross smb_authsock_close(user, so);
769b210fedeSGordon Ross status = NT_STATUS_INTERNAL_ERROR;
770b210fedeSGordon Ross goto errout;
771b210fedeSGordon Ross }
772b210fedeSGordon Ross user->u_authsock = so;
7738f70e16bSGordon Ross if (smb_auth_total_tmo != 0) {
7748f70e16bSGordon Ross user->u_auth_tmo = timeout(smb_user_auth_tmo, user,
7758f70e16bSGordon Ross SEC_TO_TICK(smb_auth_total_tmo));
7768f70e16bSGordon Ross }
777b210fedeSGordon Ross mutex_exit(&user->u_mutex);
778b210fedeSGordon Ross
77912b65585SGordon Ross /*
78012b65585SGordon Ross * Set the send/recv timeouts.
78112b65585SGordon Ross */
78212b65585SGordon Ross (void) ksocket_setsockopt(so, SOL_SOCKET, SO_SNDTIMEO,
78312b65585SGordon Ross &smb_auth_send_tmo, sizeof (smb_auth_send_tmo), CRED());
78412b65585SGordon Ross (void) ksocket_setsockopt(so, SOL_SOCKET, SO_RCVTIMEO,
78512b65585SGordon Ross &smb_auth_recv_tmo, sizeof (smb_auth_recv_tmo), CRED());
78612b65585SGordon Ross
78712b65585SGordon Ross /*
788*66b505f1SGordon Ross * Prepare for cancellable connect.
78912b65585SGordon Ross */
790b210fedeSGordon Ross mutex_enter(&sr->sr_mutex);
791b210fedeSGordon Ross if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
792b210fedeSGordon Ross mutex_exit(&sr->sr_mutex);
793b210fedeSGordon Ross status = NT_STATUS_CANCELLED;
794b210fedeSGordon Ross goto errout;
795b210fedeSGordon Ross }
796b210fedeSGordon Ross sr->sr_state = SMB_REQ_STATE_WAITING_AUTH;
797b210fedeSGordon Ross sr->cancel_method = smb_authsock_cancel;
798b210fedeSGordon Ross sr->cancel_arg2 = user;
799b210fedeSGordon Ross mutex_exit(&sr->sr_mutex);
800b210fedeSGordon Ross
801*66b505f1SGordon Ross /*
802*66b505f1SGordon Ross * Connect to the smbd auth. service.
803*66b505f1SGordon Ross *
804*66b505f1SGordon Ross * Would like to set the connect timeout too, but there's
805*66b505f1SGordon Ross * apparently no easy way to do that for AF_UNIX.
806*66b505f1SGordon Ross */
80712b65585SGordon Ross rc = ksocket_connect(so, (struct sockaddr *)&smbauth_sockname,
80812b65585SGordon Ross sizeof (smbauth_sockname), CRED());
80912b65585SGordon Ross if (rc != 0) {
81012b65585SGordon Ross DTRACE_PROBE1(error, int, rc);
81112b65585SGordon Ross status = NT_STATUS_NETLOGON_NOT_STARTED;
81212b65585SGordon Ross }
81312b65585SGordon Ross
814*66b505f1SGordon Ross /*
815*66b505f1SGordon Ross * Did connect complete or was it cancelled?
816*66b505f1SGordon Ross */
817b210fedeSGordon Ross mutex_enter(&sr->sr_mutex);
818*66b505f1SGordon Ross switch_state:
819b210fedeSGordon Ross switch (sr->sr_state) {
820b210fedeSGordon Ross case SMB_REQ_STATE_WAITING_AUTH:
821*66b505f1SGordon Ross /* Normal wakeup. Keep status from above. */
822b210fedeSGordon Ross sr->sr_state = SMB_REQ_STATE_ACTIVE;
823b210fedeSGordon Ross break;
824b210fedeSGordon Ross case SMB_REQ_STATE_CANCEL_PENDING:
825*66b505f1SGordon Ross /* cancel_method running. wait. */
826*66b505f1SGordon Ross cv_wait(&sr->sr_st_cv, &sr->sr_mutex);
827*66b505f1SGordon Ross goto switch_state;
828*66b505f1SGordon Ross case SMB_REQ_STATE_CANCELLED:
829b210fedeSGordon Ross status = NT_STATUS_CANCELLED;
830b210fedeSGordon Ross break;
831b210fedeSGordon Ross default:
83212b65585SGordon Ross status = NT_STATUS_INTERNAL_ERROR;
833b210fedeSGordon Ross break;
83412b65585SGordon Ross }
835*66b505f1SGordon Ross sr->cancel_method = NULL;
836*66b505f1SGordon Ross sr->cancel_arg2 = NULL;
837b210fedeSGordon Ross mutex_exit(&sr->sr_mutex);
83812b65585SGordon Ross
83912b65585SGordon Ross errout:
84012b65585SGordon Ross return (status);
84112b65585SGordon Ross }
84212b65585SGordon Ross
84312b65585SGordon Ross static int
smb_authsock_send(ksocket_t so,void * buf,size_t len)84412b65585SGordon Ross smb_authsock_send(ksocket_t so, void *buf, size_t len)
84512b65585SGordon Ross {
84612b65585SGordon Ross int rc;
84712b65585SGordon Ross size_t iocnt = 0;
84812b65585SGordon Ross
84912b65585SGordon Ross rc = ksocket_send(so, buf, len, 0, &iocnt, CRED());
85012b65585SGordon Ross if (rc == 0 && iocnt != len) {
85112b65585SGordon Ross DTRACE_PROBE1(short, size_t, iocnt);
85212b65585SGordon Ross rc = EIO;
85312b65585SGordon Ross }
85412b65585SGordon Ross if (rc != 0) {
85512b65585SGordon Ross DTRACE_PROBE1(error, int, rc);
85612b65585SGordon Ross }
85712b65585SGordon Ross
85812b65585SGordon Ross return (rc);
85912b65585SGordon Ross }
86012b65585SGordon Ross
86112b65585SGordon Ross static int
smb_authsock_recv(ksocket_t so,void * buf,size_t len)86212b65585SGordon Ross smb_authsock_recv(ksocket_t so, void *buf, size_t len)
86312b65585SGordon Ross {
86412b65585SGordon Ross int rc;
86512b65585SGordon Ross size_t iocnt = 0;
86612b65585SGordon Ross
86712b65585SGordon Ross rc = ksocket_recv(so, buf, len, MSG_WAITALL, &iocnt, CRED());
86812b65585SGordon Ross if (rc == 0) {
86912b65585SGordon Ross if (iocnt == 0) {
87012b65585SGordon Ross DTRACE_PROBE1(discon, struct sonode *, so);
87112b65585SGordon Ross rc = ENOTCONN;
87212b65585SGordon Ross } else if (iocnt != len) {
87312b65585SGordon Ross /* Should not happen with MSG_WAITALL */
87412b65585SGordon Ross DTRACE_PROBE1(short, size_t, iocnt);
87512b65585SGordon Ross rc = EIO;
87612b65585SGordon Ross }
87712b65585SGordon Ross }
87812b65585SGordon Ross if (rc != 0) {
87912b65585SGordon Ross DTRACE_PROBE1(error, int, rc);
88012b65585SGordon Ross }
88112b65585SGordon Ross
88212b65585SGordon Ross return (rc);
88312b65585SGordon Ross }
88412b65585SGordon Ross
885b210fedeSGordon Ross /*
886b210fedeSGordon Ross * Caller has cleared user->u_authsock, passing the last ref
887b210fedeSGordon Ross * as the 2nd arg here. This can block, so it's called
888b210fedeSGordon Ross * after exiting u_mutex.
889b210fedeSGordon Ross */
89012b65585SGordon Ross void
smb_authsock_close(smb_user_t * user,ksocket_t so)891b210fedeSGordon Ross smb_authsock_close(smb_user_t *user, ksocket_t so)
89212b65585SGordon Ross {
89312b65585SGordon Ross
8948f70e16bSGordon Ross (void) ksocket_shutdown(so, SHUT_RDWR, CRED());
895b210fedeSGordon Ross (void) ksocket_close(so, CRED());
89612b65585SGordon Ross smb_threshold_exit(&user->u_server->sv_ssetup_ct);
89712b65585SGordon Ross }
898