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 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 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 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 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 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 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 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 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 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 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 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 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