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.
2312b65585SGordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
2412b65585SGordon Ross */
2512b65585SGordon Ross
2612b65585SGordon Ross /*
2712b65585SGordon Ross * Authentication support for SMB session setup
2812b65585SGordon Ross */
2912b65585SGordon Ross
3012b65585SGordon Ross #include <sys/types.h>
3112b65585SGordon Ross #include <sys/sid.h>
3212b65585SGordon Ross #include <sys/priv_names.h>
3312b65585SGordon Ross #include <sys/socket.h>
3412b65585SGordon Ross #include <sys/un.h>
3512b65585SGordon Ross #include <netinet/in.h>
3612b65585SGordon Ross #include <smbsrv/smb_idmap.h>
3712b65585SGordon Ross #include <smbsrv/smb_kproto.h>
3812b65585SGordon Ross #include <smbsrv/smb_token.h>
3912b65585SGordon Ross
4012b65585SGordon Ross static uint32_t smb_authsock_open(smb_user_t *);
4112b65585SGordon Ross static int smb_authsock_send(ksocket_t, void *, size_t);
4212b65585SGordon Ross static int smb_authsock_recv(ksocket_t, void *, size_t);
4312b65585SGordon Ross static uint32_t smb_authsock_sendrecv(smb_user_t *, smb_lsa_msg_hdr_t *hdr,
4412b65585SGordon Ross void *sndbuf, void **recvbuf);
4512b65585SGordon Ross /* void smb_authsock_close(smb_user_t *); kproto.h */
4612b65585SGordon Ross
4712b65585SGordon Ross static uint32_t smb_auth_do_clinfo(smb_request_t *);
4812b65585SGordon Ross static uint32_t smb_auth_do_oldreq(smb_request_t *);
4912b65585SGordon Ross static uint32_t smb_auth_get_token(smb_request_t *);
5012b65585SGordon Ross static uint32_t smb_priv_xlate(smb_token_t *);
5112b65585SGordon Ross
5212b65585SGordon Ross /*
5312b65585SGordon Ross * Handle old-style session setup (non-extended security)
5412b65585SGordon Ross *
5512b65585SGordon Ross * The user information is passed to smbd for authentication.
5612b65585SGordon Ross * If smbd can authenticate the user an access token is returned and we
5712b65585SGordon Ross * generate a cred and new user based on the token.
5812b65585SGordon Ross */
5912b65585SGordon Ross int
smb_authenticate_old(smb_request_t * sr)6012b65585SGordon Ross smb_authenticate_old(smb_request_t *sr)
6112b65585SGordon Ross {
6212b65585SGordon Ross smb_user_t *user = NULL;
6312b65585SGordon Ross uint32_t status;
6412b65585SGordon Ross
6512b65585SGordon Ross user = smb_user_new(sr->session);
6612b65585SGordon Ross if (user == NULL)
6712b65585SGordon Ross return (NT_STATUS_TOO_MANY_SESSIONS);
6812b65585SGordon Ross
6912b65585SGordon Ross /* user cleanup in smb_request_free */
7012b65585SGordon Ross sr->uid_user = user;
7112b65585SGordon Ross sr->smb_uid = user->u_uid;
7212b65585SGordon Ross
7312b65585SGordon Ross /*
7412b65585SGordon Ross * Open a connection to the local logon service.
7512b65585SGordon Ross * If we can't, it may be busy, or not running.
7612b65585SGordon Ross * Don't log here - this may be frequent.
7712b65585SGordon Ross */
7812b65585SGordon Ross if ((status = smb_authsock_open(user)) != 0)
7912b65585SGordon Ross goto errout;
8012b65585SGordon Ross
8112b65585SGordon Ross /*
8212b65585SGordon Ross * Tell the auth. svc who this client is.
8312b65585SGordon Ross */
8412b65585SGordon Ross if ((status = smb_auth_do_clinfo(sr)) != 0)
8512b65585SGordon Ross goto errout;
8612b65585SGordon Ross
8712b65585SGordon Ross /*
8812b65585SGordon Ross * Authentication proper
8912b65585SGordon Ross */
9012b65585SGordon Ross if ((status = smb_auth_do_oldreq(sr)) != 0)
9112b65585SGordon Ross goto errout;
9212b65585SGordon Ross
9312b65585SGordon Ross /*
9412b65585SGordon Ross * Get the final auth. token.
9512b65585SGordon Ross */
9612b65585SGordon Ross if ((status = smb_auth_get_token(sr)) != 0)
9712b65585SGordon Ross goto errout;
9812b65585SGordon Ross
9912b65585SGordon Ross return (0);
10012b65585SGordon Ross
10112b65585SGordon Ross errout:
10212b65585SGordon Ross smb_user_logoff(user);
10312b65585SGordon Ross return (status);
10412b65585SGordon Ross }
10512b65585SGordon Ross
10612b65585SGordon Ross /*
10712b65585SGordon Ross * Build an authentication request message and
10812b65585SGordon Ross * send it to the local logon service.
10912b65585SGordon Ross */
11012b65585SGordon Ross static uint32_t
smb_auth_do_oldreq(smb_request_t * sr)11112b65585SGordon Ross smb_auth_do_oldreq(smb_request_t *sr)
11212b65585SGordon Ross {
11312b65585SGordon Ross smb_lsa_msg_hdr_t msg_hdr;
11412b65585SGordon Ross smb_logon_t user_info;
11512b65585SGordon Ross XDR xdrs;
11612b65585SGordon Ross smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
11712b65585SGordon Ross smb_user_t *user = sr->uid_user;
11812b65585SGordon Ross void *sbuf = NULL;
11912b65585SGordon Ross void *rbuf = NULL;
12012b65585SGordon Ross uint32_t slen = 0;
12112b65585SGordon Ross uint32_t rlen = 0;
12212b65585SGordon Ross uint32_t status;
12312b65585SGordon Ross bool_t ok;
12412b65585SGordon Ross
12512b65585SGordon Ross bzero(&user_info, sizeof (smb_logon_t));
12612b65585SGordon Ross
12712b65585SGordon Ross user_info.lg_level = NETR_NETWORK_LOGON;
12812b65585SGordon Ross user_info.lg_username = sinfo->ssi_user;
12912b65585SGordon Ross user_info.lg_domain = sinfo->ssi_domain;
13012b65585SGordon Ross user_info.lg_workstation = sr->session->workstation;
13112b65585SGordon Ross user_info.lg_clnt_ipaddr = sr->session->ipaddr;
13212b65585SGordon Ross user_info.lg_local_ipaddr = sr->session->local_ipaddr;
13312b65585SGordon Ross user_info.lg_local_port = sr->session->s_local_port;
13412b65585SGordon Ross user_info.lg_challenge_key.val = sr->session->challenge_key;
13512b65585SGordon Ross user_info.lg_challenge_key.len = sr->session->challenge_len;
13612b65585SGordon Ross user_info.lg_nt_password.val = sinfo->ssi_ntpwd;
13712b65585SGordon Ross user_info.lg_nt_password.len = sinfo->ssi_ntpwlen;
13812b65585SGordon Ross user_info.lg_lm_password.val = sinfo->ssi_lmpwd;
13912b65585SGordon Ross user_info.lg_lm_password.len = sinfo->ssi_lmpwlen;
14012b65585SGordon Ross user_info.lg_native_os = sr->session->native_os;
14112b65585SGordon Ross user_info.lg_native_lm = sr->session->native_lm;
14212b65585SGordon Ross /* lg_flags? */
14312b65585SGordon Ross
14412b65585SGordon Ross slen = xdr_sizeof(smb_logon_xdr, &user_info);
14512b65585SGordon Ross sbuf = kmem_alloc(slen, KM_SLEEP);
14612b65585SGordon Ross xdrmem_create(&xdrs, sbuf, slen, XDR_ENCODE);
14712b65585SGordon Ross ok = smb_logon_xdr(&xdrs, &user_info);
14812b65585SGordon Ross xdr_destroy(&xdrs);
14912b65585SGordon Ross if (!ok) {
15012b65585SGordon Ross status = RPC_NT_BAD_STUB_DATA;
15112b65585SGordon Ross goto out;
15212b65585SGordon Ross }
15312b65585SGordon Ross
15412b65585SGordon Ross msg_hdr.lmh_msgtype = LSA_MTYPE_OLDREQ;
15512b65585SGordon Ross msg_hdr.lmh_msglen = slen;
15612b65585SGordon Ross status = smb_authsock_sendrecv(user, &msg_hdr, sbuf, &rbuf);
15712b65585SGordon Ross if (status != 0)
15812b65585SGordon Ross goto out;
15912b65585SGordon Ross rlen = msg_hdr.lmh_msglen;
16012b65585SGordon Ross kmem_free(sbuf, slen);
16112b65585SGordon Ross sbuf = NULL;
16212b65585SGordon Ross
16312b65585SGordon Ross /*
16412b65585SGordon Ross * Decode the response message.
16512b65585SGordon Ross */
16612b65585SGordon Ross switch (msg_hdr.lmh_msgtype) {
16712b65585SGordon Ross
16812b65585SGordon Ross case LSA_MTYPE_OK:
16912b65585SGordon Ross status = 0;
17012b65585SGordon Ross break;
17112b65585SGordon Ross
17212b65585SGordon Ross case LSA_MTYPE_ERROR:
17312b65585SGordon Ross if (rlen == sizeof (smb_lsa_eresp_t)) {
17412b65585SGordon Ross smb_lsa_eresp_t *ler = rbuf;
17512b65585SGordon Ross status = ler->ler_ntstatus;
17612b65585SGordon Ross break;
17712b65585SGordon Ross }
17812b65585SGordon Ross /* FALLTHROUGH */
17912b65585SGordon Ross
18012b65585SGordon Ross default: /* Bogus message type */
18112b65585SGordon Ross status = NT_STATUS_INTERNAL_ERROR;
18212b65585SGordon Ross break;
18312b65585SGordon Ross }
18412b65585SGordon Ross
18512b65585SGordon Ross out:
18612b65585SGordon Ross if (rbuf != NULL)
18712b65585SGordon Ross kmem_free(rbuf, rlen);
18812b65585SGordon Ross if (sbuf != NULL)
18912b65585SGordon Ross kmem_free(sbuf, slen);
19012b65585SGordon Ross
19112b65585SGordon Ross return (status);
19212b65585SGordon Ross }
19312b65585SGordon Ross
19412b65585SGordon Ross /*
19512b65585SGordon Ross * Handle new-style (extended security) session setup.
19612b65585SGordon Ross * Returns zero: success, non-zero: error (value not used)
19712b65585SGordon Ross *
19812b65585SGordon Ross * Note that this style uses a sequence of session setup requests,
19912b65585SGordon Ross * where the first has SMB UID=0, and subsequent requests in the
20012b65585SGordon Ross * same authentication sequence have the SMB UID returned for that
20112b65585SGordon Ross * first request. We allocate a USER object when the first request
20212b65585SGordon Ross * in the sequence arrives (SMB_USER_STATE_LOGGING_ON) and use that
20312b65585SGordon Ross * to maintain state between requests in this sequence. The state
20412b65585SGordon Ross * for one sequence includes an AF_UNIX "authsock" connection to the
20512b65585SGordon Ross * user-space smbd. The neat part of this is: in smbd, the handler
20612b65585SGordon Ross * for the server-side of one authsock gets only request specific to
20712b65585SGordon Ross * one authentication sequence, simplifying it's work immensely.
20812b65585SGordon Ross * When the authentication sequence is finished, with either success
20912b65585SGordon Ross * or failure, the local side of the authsock is closed.
21012b65585SGordon Ross *
21112b65585SGordon Ross * As with the old-style authentication, if we succeed, then the
21212b65585SGordon Ross * last message from smbd will be an smb_token_t encoding the
21312b65585SGordon Ross * information about the new user.
21412b65585SGordon Ross *
21512b65585SGordon Ross * Outline:
21612b65585SGordon Ross * (a) On the first request (UID==0) create a USER object,
21712b65585SGordon Ross * and on subsequent requests, find USER by SMB UID.
21812b65585SGordon Ross * (b) Send message / recv. response as above,
21912b65585SGordon Ross * (c) If response says "we're done", close authsock
22012b65585SGordon Ross * (both success and failure must close authsock)
22112b65585SGordon Ross */
22212b65585SGordon Ross int
smb_authenticate_ext(smb_request_t * sr)22312b65585SGordon Ross smb_authenticate_ext(smb_request_t *sr)
22412b65585SGordon Ross {
22512b65585SGordon Ross smb_lsa_msg_hdr_t msg_hdr;
22612b65585SGordon Ross smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
22712b65585SGordon Ross smb_user_t *user = NULL;
22812b65585SGordon Ross void *rbuf = NULL;
22912b65585SGordon Ross uint32_t rlen = 0;
23012b65585SGordon Ross uint32_t status;
23112b65585SGordon Ross
23212b65585SGordon Ross ASSERT(sr->uid_user == NULL);
23312b65585SGordon Ross
23412b65585SGordon Ross /*
23512b65585SGordon Ross * On the first request (UID==0) create a USER object.
23612b65585SGordon Ross * On subsequent requests (UID!=0) find the USER object.
23712b65585SGordon Ross * Either way, sr->uid_user is set, so our ref. on the
23812b65585SGordon Ross * user object is dropped during normal cleanup work
23912b65585SGordon Ross * for the smb_request (sr). Ditto u_authsock.
24012b65585SGordon Ross */
24112b65585SGordon Ross if (sr->smb_uid == 0) {
24212b65585SGordon Ross user = smb_user_new(sr->session);
24312b65585SGordon Ross if (user == NULL)
24412b65585SGordon Ross return (NT_STATUS_TOO_MANY_SESSIONS);
24512b65585SGordon Ross
24612b65585SGordon Ross /* user cleanup in smb_request_free */
24712b65585SGordon Ross sr->uid_user = user;
24812b65585SGordon Ross sr->smb_uid = user->u_uid;
24912b65585SGordon Ross
25012b65585SGordon Ross /*
25112b65585SGordon Ross * Open a connection to the local logon service.
25212b65585SGordon Ross * If we can't, it may be busy, or not running.
25312b65585SGordon Ross * Don't log here - this may be frequent.
25412b65585SGordon Ross */
25512b65585SGordon Ross if ((status = smb_authsock_open(user)) != 0)
25612b65585SGordon Ross goto errout;
25712b65585SGordon Ross
25812b65585SGordon Ross /*
25912b65585SGordon Ross * Tell the auth. svc who this client is.
26012b65585SGordon Ross */
26112b65585SGordon Ross if ((status = smb_auth_do_clinfo(sr)) != 0)
26212b65585SGordon Ross goto errout;
26312b65585SGordon Ross
26412b65585SGordon Ross msg_hdr.lmh_msgtype = LSA_MTYPE_ESFIRST;
26512b65585SGordon Ross } else {
26612b65585SGordon Ross user = smb_session_lookup_uid_st(sr->session,
26712b65585SGordon Ross sr->smb_uid, SMB_USER_STATE_LOGGING_ON);
26812b65585SGordon Ross if (user == NULL)
26912b65585SGordon Ross return (NT_STATUS_USER_SESSION_DELETED);
27012b65585SGordon Ross
27112b65585SGordon Ross /* user cleanup in smb_request_free */
27212b65585SGordon Ross sr->uid_user = user;
27312b65585SGordon Ross
27412b65585SGordon Ross msg_hdr.lmh_msgtype = LSA_MTYPE_ESNEXT;
27512b65585SGordon Ross }
27612b65585SGordon Ross
27712b65585SGordon Ross /*
27812b65585SGordon Ross * Wrap the "security blob" with our header
27912b65585SGordon Ross * (LSA_MTYPE_ESFIRST or LSA_MTYPE_ESNEXT)
28012b65585SGordon Ross * and send it up the authsock with either
28112b65585SGordon Ross */
28212b65585SGordon Ross msg_hdr.lmh_msglen = sinfo->ssi_iseclen;
28312b65585SGordon Ross status = smb_authsock_sendrecv(user, &msg_hdr,
28412b65585SGordon Ross sinfo->ssi_isecblob, &rbuf);
28512b65585SGordon Ross if (status != 0)
28612b65585SGordon Ross goto errout;
28712b65585SGordon Ross rlen = msg_hdr.lmh_msglen;
28812b65585SGordon Ross
28912b65585SGordon Ross /*
29012b65585SGordon Ross * Decode the response message.
29112b65585SGordon Ross * Note: allocated rbuf
29212b65585SGordon Ross */
29312b65585SGordon Ross switch (msg_hdr.lmh_msgtype) {
29412b65585SGordon Ross
29512b65585SGordon Ross case LSA_MTYPE_ES_CONT:
29612b65585SGordon Ross sinfo->ssi_oseclen = (uint16_t)rlen;
29712b65585SGordon Ross sinfo->ssi_osecblob = smb_srm_alloc(sr, sinfo->ssi_oseclen);
29812b65585SGordon Ross bcopy(rbuf, sinfo->ssi_osecblob, sinfo->ssi_oseclen);
29912b65585SGordon Ross /*
30012b65585SGordon Ross * This is not really an error, but tells the client
30112b65585SGordon Ross * it should send another session setup request.
30212b65585SGordon Ross */
30312b65585SGordon Ross status = NT_STATUS_MORE_PROCESSING_REQUIRED;
30412b65585SGordon Ross break;
30512b65585SGordon Ross
30612b65585SGordon Ross case LSA_MTYPE_ES_DONE:
30712b65585SGordon Ross sinfo->ssi_oseclen = (uint16_t)rlen;
30812b65585SGordon Ross sinfo->ssi_osecblob = smb_srm_alloc(sr, sinfo->ssi_oseclen);
30912b65585SGordon Ross bcopy(rbuf, sinfo->ssi_osecblob, sinfo->ssi_oseclen);
31012b65585SGordon Ross sinfo->ssi_ntpwlen = 0;
31112b65585SGordon Ross /*
31212b65585SGordon Ross * Get the final auth. token.
31312b65585SGordon Ross */
31412b65585SGordon Ross status = smb_auth_get_token(sr);
31512b65585SGordon Ross break;
31612b65585SGordon Ross
31712b65585SGordon Ross case LSA_MTYPE_ERROR:
31812b65585SGordon Ross /*
31912b65585SGordon Ross * Authentication failed. Return the error
32012b65585SGordon Ross * provided in the reply message.
32112b65585SGordon Ross */
32212b65585SGordon Ross if (rlen == sizeof (smb_lsa_eresp_t)) {
32312b65585SGordon Ross smb_lsa_eresp_t *ler = rbuf;
32412b65585SGordon Ross status = ler->ler_ntstatus;
32512b65585SGordon Ross goto errout;
32612b65585SGordon Ross }
32712b65585SGordon Ross /* FALLTHROUGH */
32812b65585SGordon Ross
32912b65585SGordon Ross default: /* Bogus message type */
33012b65585SGordon Ross status = NT_STATUS_INTERNAL_ERROR;
33112b65585SGordon Ross goto errout;
33212b65585SGordon Ross }
33312b65585SGordon Ross
33412b65585SGordon Ross if (status != 0 && status != NT_STATUS_MORE_PROCESSING_REQUIRED) {
33512b65585SGordon Ross errout:
33612b65585SGordon Ross smb_user_logoff(user);
33712b65585SGordon Ross }
33812b65585SGordon Ross
33912b65585SGordon Ross if (rbuf != NULL)
34012b65585SGordon Ross kmem_free(rbuf, rlen);
34112b65585SGordon Ross
34212b65585SGordon Ross return (status);
34312b65585SGordon Ross }
34412b65585SGordon Ross
34512b65585SGordon Ross /*
34612b65585SGordon Ross * Send the "client info" up to the auth service.
34712b65585SGordon Ross */
34812b65585SGordon Ross static uint32_t
smb_auth_do_clinfo(smb_request_t * sr)34912b65585SGordon Ross smb_auth_do_clinfo(smb_request_t *sr)
35012b65585SGordon Ross {
35112b65585SGordon Ross smb_lsa_msg_hdr_t msg_hdr;
35212b65585SGordon Ross smb_lsa_clinfo_t clinfo;
35312b65585SGordon Ross smb_user_t *user = sr->uid_user;
35412b65585SGordon Ross void *rbuf = NULL;
35512b65585SGordon Ross uint32_t status;
35612b65585SGordon Ross
35712b65585SGordon Ross /*
35812b65585SGordon Ross * Send a message with info. about the client
35912b65585SGordon Ross * (IP address, etc) and wait for an ACK.
36012b65585SGordon Ross */
36112b65585SGordon Ross msg_hdr.lmh_msgtype = LSA_MTYPE_CLINFO;
36212b65585SGordon Ross msg_hdr.lmh_msglen = sizeof (clinfo);
36312b65585SGordon Ross clinfo.lci_clnt_ipaddr = sr->session->ipaddr;
36412b65585SGordon Ross (void) memcpy(clinfo.lci_challenge_key,
36512b65585SGordon Ross sr->session->challenge_key,
36612b65585SGordon Ross sizeof (clinfo.lci_challenge_key));
36712b65585SGordon Ross status = smb_authsock_sendrecv(user, &msg_hdr, &clinfo, &rbuf);
36812b65585SGordon Ross /* We don't use this response. */
36912b65585SGordon Ross if (rbuf != NULL) {
37012b65585SGordon Ross kmem_free(rbuf, msg_hdr.lmh_msglen);
37112b65585SGordon Ross rbuf = NULL;
37212b65585SGordon Ross }
37312b65585SGordon Ross
37412b65585SGordon Ross return (status);
37512b65585SGordon Ross }
37612b65585SGordon Ross
37712b65585SGordon Ross /*
37812b65585SGordon Ross * After a successful authentication, ask the authsvc to
37912b65585SGordon Ross * send us the authentication token.
38012b65585SGordon Ross */
38112b65585SGordon Ross static uint32_t
smb_auth_get_token(smb_request_t * sr)38212b65585SGordon Ross smb_auth_get_token(smb_request_t *sr)
38312b65585SGordon Ross {
38412b65585SGordon Ross smb_lsa_msg_hdr_t msg_hdr;
38512b65585SGordon Ross XDR xdrs;
38612b65585SGordon Ross smb_user_t *user = sr->uid_user;
38712b65585SGordon Ross smb_token_t *token = NULL;
38812b65585SGordon Ross cred_t *cr = NULL;
38912b65585SGordon Ross void *rbuf = NULL;
39012b65585SGordon Ross uint32_t rlen = 0;
39112b65585SGordon Ross uint32_t privileges;
39212b65585SGordon Ross uint32_t status;
393*a90cf9f2SGordon Ross int rc;
39412b65585SGordon Ross bool_t ok;
39512b65585SGordon Ross
39612b65585SGordon Ross msg_hdr.lmh_msgtype = LSA_MTYPE_GETTOK;
39712b65585SGordon Ross msg_hdr.lmh_msglen = 0;
39812b65585SGordon Ross
39912b65585SGordon Ross status = smb_authsock_sendrecv(user, &msg_hdr, NULL, &rbuf);
40012b65585SGordon Ross if (status != 0)
40112b65585SGordon Ross goto errout;
40212b65585SGordon Ross
40312b65585SGordon Ross rlen = msg_hdr.lmh_msglen;
40412b65585SGordon Ross switch (msg_hdr.lmh_msgtype) {
40512b65585SGordon Ross
40612b65585SGordon Ross case LSA_MTYPE_TOKEN:
40712b65585SGordon Ross status = 0;
40812b65585SGordon Ross break;
40912b65585SGordon Ross
41012b65585SGordon Ross case LSA_MTYPE_ERROR:
41112b65585SGordon Ross if (rlen == sizeof (smb_lsa_eresp_t)) {
41212b65585SGordon Ross smb_lsa_eresp_t *ler = rbuf;
41312b65585SGordon Ross status = ler->ler_ntstatus;
41412b65585SGordon Ross goto errout;
41512b65585SGordon Ross }
41612b65585SGordon Ross /* FALLTHROUGH */
41712b65585SGordon Ross
41812b65585SGordon Ross default:
41912b65585SGordon Ross status = NT_STATUS_INTERNAL_ERROR;
42012b65585SGordon Ross goto errout;
42112b65585SGordon Ross }
42212b65585SGordon Ross
42312b65585SGordon Ross /*
42412b65585SGordon Ross * Authenticated. Decode the LSA_MTYPE_TOKEN.
42512b65585SGordon Ross */
42612b65585SGordon Ross xdrmem_create(&xdrs, rbuf, rlen, XDR_DECODE);
42712b65585SGordon Ross token = kmem_zalloc(sizeof (smb_token_t), KM_SLEEP);
42812b65585SGordon Ross ok = smb_token_xdr(&xdrs, token);
42912b65585SGordon Ross xdr_destroy(&xdrs);
43012b65585SGordon Ross if (!ok) {
43112b65585SGordon Ross status = RPC_NT_BAD_STUB_DATA;
43212b65585SGordon Ross goto errout;
43312b65585SGordon Ross }
43412b65585SGordon Ross kmem_free(rbuf, rlen);
43512b65585SGordon Ross rbuf = NULL;
43612b65585SGordon Ross
43712b65585SGordon Ross /*
43812b65585SGordon Ross * Setup the logon object.
43912b65585SGordon Ross */
44012b65585SGordon Ross cr = smb_cred_create(token);
44112b65585SGordon Ross if (cr == NULL)
44212b65585SGordon Ross goto errout;
44312b65585SGordon Ross privileges = smb_priv_xlate(token);
44412b65585SGordon Ross (void) smb_user_logon(user, cr,
44512b65585SGordon Ross token->tkn_domain_name, token->tkn_account_name,
44612b65585SGordon Ross token->tkn_flags, privileges, token->tkn_audit_sid);
44712b65585SGordon Ross crfree(cr);
44812b65585SGordon Ross
44912b65585SGordon Ross /*
45012b65585SGordon Ross * Save the session key, and (maybe) enable signing,
45112b65585SGordon Ross * but only for real logon (not ANON or GUEST).
45212b65585SGordon Ross */
45312b65585SGordon Ross if ((token->tkn_flags & (SMB_ATF_GUEST | SMB_ATF_ANON)) == 0) {
454*a90cf9f2SGordon Ross if (sr->session->dialect >= SMB_VERS_2_BASE) {
455*a90cf9f2SGordon Ross rc = smb2_sign_begin(sr, token);
456*a90cf9f2SGordon Ross } else {
457*a90cf9f2SGordon Ross rc = smb_sign_begin(sr, token);
458*a90cf9f2SGordon Ross }
459*a90cf9f2SGordon Ross if (rc != 0) {
46012b65585SGordon Ross status = NT_STATUS_INTERNAL_ERROR;
46112b65585SGordon Ross goto errout;
46212b65585SGordon Ross }
46312b65585SGordon Ross }
46412b65585SGordon Ross
46512b65585SGordon Ross smb_token_free(token);
46612b65585SGordon Ross
46712b65585SGordon Ross sr->user_cr = user->u_cred;
46812b65585SGordon Ross return (0);
46912b65585SGordon Ross
47012b65585SGordon Ross errout:
47112b65585SGordon Ross if (rbuf != NULL)
47212b65585SGordon Ross kmem_free(rbuf, rlen);
47312b65585SGordon Ross if (token != NULL)
47412b65585SGordon Ross smb_token_free(token);
47512b65585SGordon Ross return (status);
47612b65585SGordon Ross }
47712b65585SGordon Ross
47812b65585SGordon Ross /*
47912b65585SGordon Ross * Tokens are allocated in the kernel via XDR.
48012b65585SGordon Ross * Call xdr_free before freeing the token structure.
48112b65585SGordon Ross */
48212b65585SGordon Ross void
smb_token_free(smb_token_t * token)48312b65585SGordon Ross smb_token_free(smb_token_t *token)
48412b65585SGordon Ross {
48512b65585SGordon Ross if (token != NULL) {
48612b65585SGordon Ross xdr_free(smb_token_xdr, (char *)token);
48712b65585SGordon Ross kmem_free(token, sizeof (smb_token_t));
48812b65585SGordon Ross }
48912b65585SGordon Ross }
49012b65585SGordon Ross
49112b65585SGordon Ross /*
49212b65585SGordon Ross * Convert access token privileges to local definitions.
49312b65585SGordon Ross */
49412b65585SGordon Ross static uint32_t
smb_priv_xlate(smb_token_t * token)49512b65585SGordon Ross smb_priv_xlate(smb_token_t *token)
49612b65585SGordon Ross {
49712b65585SGordon Ross uint32_t privileges = 0;
49812b65585SGordon Ross
49912b65585SGordon Ross if (smb_token_query_privilege(token, SE_BACKUP_LUID))
50012b65585SGordon Ross privileges |= SMB_USER_PRIV_BACKUP;
50112b65585SGordon Ross
50212b65585SGordon Ross if (smb_token_query_privilege(token, SE_RESTORE_LUID))
50312b65585SGordon Ross privileges |= SMB_USER_PRIV_RESTORE;
50412b65585SGordon Ross
50512b65585SGordon Ross if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID))
50612b65585SGordon Ross privileges |= SMB_USER_PRIV_TAKE_OWNERSHIP;
50712b65585SGordon Ross
50812b65585SGordon Ross if (smb_token_query_privilege(token, SE_SECURITY_LUID))
50912b65585SGordon Ross privileges |= SMB_USER_PRIV_SECURITY;
51012b65585SGordon Ross
51112b65585SGordon Ross return (privileges);
51212b65585SGordon Ross }
51312b65585SGordon Ross
51412b65585SGordon Ross /*
51512b65585SGordon Ross * Send/recv a request/reply sequence on the auth socket.
51612b65585SGordon Ross * Returns zero or an NT status.
51712b65585SGordon Ross *
51812b65585SGordon Ross * Errors here mean we can't communicate with the smbd_authsvc.
51912b65585SGordon Ross * With limited authsock instances, this should be rare.
52012b65585SGordon Ross */
52112b65585SGordon Ross static uint32_t
smb_authsock_sendrecv(smb_user_t * user,smb_lsa_msg_hdr_t * hdr,void * sndbuf,void ** recvbuf)52212b65585SGordon Ross smb_authsock_sendrecv(smb_user_t *user, smb_lsa_msg_hdr_t *hdr,
52312b65585SGordon Ross void *sndbuf, void **recvbuf)
52412b65585SGordon Ross {
52512b65585SGordon Ross ksocket_t so;
52612b65585SGordon Ross uint32_t status;
52712b65585SGordon Ross int rc;
52812b65585SGordon Ross
52912b65585SGordon Ross /*
53012b65585SGordon Ross * Get a hold on the auth socket.
53112b65585SGordon Ross */
53212b65585SGordon Ross mutex_enter(&user->u_mutex);
53312b65585SGordon Ross so = user->u_authsock;
53412b65585SGordon Ross if (so == NULL) {
53512b65585SGordon Ross mutex_exit(&user->u_mutex);
53612b65585SGordon Ross return (NT_STATUS_INTERNAL_ERROR);
53712b65585SGordon Ross }
53812b65585SGordon Ross ksocket_hold(so);
53912b65585SGordon Ross mutex_exit(&user->u_mutex);
54012b65585SGordon Ross
54112b65585SGordon Ross rc = smb_authsock_send(so, hdr, sizeof (*hdr));
54212b65585SGordon Ross if (rc == 0 && hdr->lmh_msglen != 0) {
54312b65585SGordon Ross rc = smb_authsock_send(so, sndbuf, hdr->lmh_msglen);
54412b65585SGordon Ross }
54512b65585SGordon Ross if (rc)
54612b65585SGordon Ross goto out;
54712b65585SGordon Ross
54812b65585SGordon Ross rc = smb_authsock_recv(so, hdr, sizeof (*hdr));
54912b65585SGordon Ross if (rc == 0 && hdr->lmh_msglen != 0) {
55012b65585SGordon Ross *recvbuf = kmem_alloc(hdr->lmh_msglen, KM_SLEEP);
55112b65585SGordon Ross rc = smb_authsock_recv(so, *recvbuf, hdr->lmh_msglen);
55212b65585SGordon Ross if (rc) {
55312b65585SGordon Ross kmem_free(*recvbuf, hdr->lmh_msglen);
55412b65585SGordon Ross *recvbuf = NULL;
55512b65585SGordon Ross }
55612b65585SGordon Ross }
55712b65585SGordon Ross
55812b65585SGordon Ross out:
55912b65585SGordon Ross ksocket_rele(so);
56012b65585SGordon Ross switch (rc) {
56112b65585SGordon Ross case 0:
56212b65585SGordon Ross status = 0;
56312b65585SGordon Ross break;
56412b65585SGordon Ross case EIO:
56512b65585SGordon Ross status = RPC_NT_COMM_FAILURE;
56612b65585SGordon Ross break;
56712b65585SGordon Ross case ENOTCONN:
56812b65585SGordon Ross status = RPC_NT_PIPE_CLOSED;
56912b65585SGordon Ross break;
57012b65585SGordon Ross default:
57112b65585SGordon Ross status = RPC_NT_CALL_FAILED;
57212b65585SGordon Ross break;
57312b65585SGordon Ross }
57412b65585SGordon Ross
57512b65585SGordon Ross return (status);
57612b65585SGordon Ross }
57712b65585SGordon Ross
57812b65585SGordon Ross /*
57912b65585SGordon Ross * Hope this is interpreted per-zone...
58012b65585SGordon Ross */
58112b65585SGordon Ross static struct sockaddr_un smbauth_sockname = {
58212b65585SGordon Ross AF_UNIX, SMB_AUTHSVC_SOCKNAME };
58312b65585SGordon Ross
58412b65585SGordon Ross /*
58512b65585SGordon Ross * Limit how long smb_authsock_sendrecv() will wait for a
58612b65585SGordon Ross * response from the local authentication service.
58712b65585SGordon Ross */
58812b65585SGordon Ross struct timeval smb_auth_recv_tmo = { 45, 0 };
58912b65585SGordon Ross
59012b65585SGordon Ross /*
59112b65585SGordon Ross * Also limit the time smb_authsock_sendrecv() will wait
59212b65585SGordon Ross * trying to send a request to the authentication service.
59312b65585SGordon Ross */
59412b65585SGordon Ross struct timeval smb_auth_send_tmo = { 15, 0 };
59512b65585SGordon Ross
59612b65585SGordon Ross static uint32_t
smb_authsock_open(smb_user_t * user)59712b65585SGordon Ross smb_authsock_open(smb_user_t *user)
59812b65585SGordon Ross {
59912b65585SGordon Ross smb_server_t *sv = user->u_server;
60012b65585SGordon Ross ksocket_t so = NULL;
60112b65585SGordon Ross uint32_t status;
60212b65585SGordon Ross int rc;
60312b65585SGordon Ross
60412b65585SGordon Ross /*
60512b65585SGordon Ross * If the auth. service is busy, wait our turn.
60612b65585SGordon Ross * This may be frequent, so don't log.
60712b65585SGordon Ross */
60812b65585SGordon Ross if ((rc = smb_threshold_enter(&sv->sv_ssetup_ct)) != 0)
60912b65585SGordon Ross return (NT_STATUS_NO_LOGON_SERVERS);
61012b65585SGordon Ross
61112b65585SGordon Ross rc = ksocket_socket(&so, AF_UNIX, SOCK_STREAM, 0,
61212b65585SGordon Ross KSOCKET_SLEEP, CRED());
61312b65585SGordon Ross if (rc != 0) {
61412b65585SGordon Ross cmn_err(CE_NOTE, "smb_authsock_open: socket, rc=%d", rc);
61512b65585SGordon Ross status = NT_STATUS_INSUFF_SERVER_RESOURCES;
61612b65585SGordon Ross goto errout;
61712b65585SGordon Ross }
61812b65585SGordon Ross
61912b65585SGordon Ross /*
62012b65585SGordon Ross * Set the send/recv timeouts.
62112b65585SGordon Ross */
62212b65585SGordon Ross (void) ksocket_setsockopt(so, SOL_SOCKET, SO_SNDTIMEO,
62312b65585SGordon Ross &smb_auth_send_tmo, sizeof (smb_auth_send_tmo), CRED());
62412b65585SGordon Ross (void) ksocket_setsockopt(so, SOL_SOCKET, SO_RCVTIMEO,
62512b65585SGordon Ross &smb_auth_recv_tmo, sizeof (smb_auth_recv_tmo), CRED());
62612b65585SGordon Ross
62712b65585SGordon Ross /*
62812b65585SGordon Ross * Connect to the smbd auth. service.
62912b65585SGordon Ross *
63012b65585SGordon Ross * Would like to set the connect timeout too, but there's
63112b65585SGordon Ross * apparently no easy way to do that for AF_UNIX.
63212b65585SGordon Ross */
63312b65585SGordon Ross rc = ksocket_connect(so, (struct sockaddr *)&smbauth_sockname,
63412b65585SGordon Ross sizeof (smbauth_sockname), CRED());
63512b65585SGordon Ross if (rc != 0) {
63612b65585SGordon Ross DTRACE_PROBE1(error, int, rc);
63712b65585SGordon Ross status = NT_STATUS_NETLOGON_NOT_STARTED;
63812b65585SGordon Ross goto errout;
63912b65585SGordon Ross }
64012b65585SGordon Ross
64112b65585SGordon Ross /* Note: u_authsock cleanup in smb_authsock_close() */
64212b65585SGordon Ross mutex_enter(&user->u_mutex);
64312b65585SGordon Ross if (user->u_authsock != NULL) {
64412b65585SGordon Ross mutex_exit(&user->u_mutex);
64512b65585SGordon Ross status = NT_STATUS_INTERNAL_ERROR;
64612b65585SGordon Ross goto errout;
64712b65585SGordon Ross }
64812b65585SGordon Ross user->u_authsock = so;
64912b65585SGordon Ross mutex_exit(&user->u_mutex);
65012b65585SGordon Ross return (0);
65112b65585SGordon Ross
65212b65585SGordon Ross errout:
65312b65585SGordon Ross if (so != NULL)
65412b65585SGordon Ross (void) ksocket_close(so, CRED());
65512b65585SGordon Ross smb_threshold_exit(&sv->sv_ssetup_ct);
65612b65585SGordon Ross
65712b65585SGordon Ross return (status);
65812b65585SGordon Ross }
65912b65585SGordon Ross
66012b65585SGordon Ross static int
smb_authsock_send(ksocket_t so,void * buf,size_t len)66112b65585SGordon Ross smb_authsock_send(ksocket_t so, void *buf, size_t len)
66212b65585SGordon Ross {
66312b65585SGordon Ross int rc;
66412b65585SGordon Ross size_t iocnt = 0;
66512b65585SGordon Ross
66612b65585SGordon Ross rc = ksocket_send(so, buf, len, 0, &iocnt, CRED());
66712b65585SGordon Ross if (rc == 0 && iocnt != len) {
66812b65585SGordon Ross DTRACE_PROBE1(short, size_t, iocnt);
66912b65585SGordon Ross rc = EIO;
67012b65585SGordon Ross }
67112b65585SGordon Ross if (rc != 0) {
67212b65585SGordon Ross DTRACE_PROBE1(error, int, rc);
67312b65585SGordon Ross }
67412b65585SGordon Ross
67512b65585SGordon Ross return (rc);
67612b65585SGordon Ross }
67712b65585SGordon Ross
67812b65585SGordon Ross static int
smb_authsock_recv(ksocket_t so,void * buf,size_t len)67912b65585SGordon Ross smb_authsock_recv(ksocket_t so, void *buf, size_t len)
68012b65585SGordon Ross {
68112b65585SGordon Ross int rc;
68212b65585SGordon Ross size_t iocnt = 0;
68312b65585SGordon Ross
68412b65585SGordon Ross rc = ksocket_recv(so, buf, len, MSG_WAITALL, &iocnt, CRED());
68512b65585SGordon Ross if (rc == 0) {
68612b65585SGordon Ross if (iocnt == 0) {
68712b65585SGordon Ross DTRACE_PROBE1(discon, struct sonode *, so);
68812b65585SGordon Ross rc = ENOTCONN;
68912b65585SGordon Ross } else if (iocnt != len) {
69012b65585SGordon Ross /* Should not happen with MSG_WAITALL */
69112b65585SGordon Ross DTRACE_PROBE1(short, size_t, iocnt);
69212b65585SGordon Ross rc = EIO;
69312b65585SGordon Ross }
69412b65585SGordon Ross }
69512b65585SGordon Ross if (rc != 0) {
69612b65585SGordon Ross DTRACE_PROBE1(error, int, rc);
69712b65585SGordon Ross }
69812b65585SGordon Ross
69912b65585SGordon Ross return (rc);
70012b65585SGordon Ross }
70112b65585SGordon Ross
70212b65585SGordon Ross void
smb_authsock_close(smb_user_t * user)70312b65585SGordon Ross smb_authsock_close(smb_user_t *user)
70412b65585SGordon Ross {
70512b65585SGordon Ross
70612b65585SGordon Ross ASSERT(MUTEX_HELD(&user->u_mutex));
70712b65585SGordon Ross if (user->u_authsock == NULL)
70812b65585SGordon Ross return;
70912b65585SGordon Ross (void) ksocket_close(user->u_authsock, CRED());
71012b65585SGordon Ross user->u_authsock = NULL;
71112b65585SGordon Ross smb_threshold_exit(&user->u_server->sv_ssetup_ct);
71212b65585SGordon Ross }
713