コード例 #1
0
/*
 * Tries to authenticate the connected user.
 *
 * It first tries to see if the user has already been authenticated.
 * If a match is found, the user structure in the session is duplicated
 * and the function returns. Otherwise, user information is passed to
 * smbd for authentication. If smbd can authenticate the user an access
 * token structure is returned. A cred_t and user structure is created
 * based on the returned access token.
 */
static int
smb_authenticate(smb_request_t *sr, smb_sessionsetup_info_t *sinfo,
    smb_session_key_t **session_key)
{
	char *hostname = sr->sr_cfg->skc_hostname;
	int security = sr->sr_cfg->skc_secmode;
	smb_token_t *usr_token = NULL;
	smb_user_t *user = NULL;
	netr_client_t clnt_info;
	boolean_t need_lookup = B_FALSE;
	uint32_t privileges;
	cred_t *cr;
	char *buf = NULL;
	char *p;

	bzero(&clnt_info, sizeof (netr_client_t));

	if ((sinfo->ssi_cspwlen == 0) &&
	    (sinfo->ssi_cipwlen == 0 ||
	    (sinfo->ssi_cipwlen == 1 && *sinfo->ssi_cipwd == 0))) {
		clnt_info.e_username = "******";
	} else {
		clnt_info.e_username = sinfo->ssi_user;
	}
	clnt_info.e_domain = sinfo->ssi_domain;

	/*
	 * Handle user@domain format.
	 *
	 * We need to extract the user and domain names but
	 * should keep the request data as is. This is important
	 * for some forms of authentication.
	 */
	if (*sinfo->ssi_domain == '\0') {
		buf = smb_strdup(sinfo->ssi_user);
		if ((p = strchr(buf, '@')) != NULL) {
			*p = '\0';
			clnt_info.e_username = buf;
			clnt_info.e_domain = p + 1;
		}
	}

	/*
	 * See if this user has already been authenticated.
	 *
	 * If no domain name is provided we cannot determine whether
	 * this is a local or domain user when server is operating
	 * in domain mode, so lookup will be done after authentication.
	 */
	if (security == SMB_SECMODE_WORKGRP) {
		user = smb_session_dup_user(sr->session, hostname,
		    clnt_info.e_username);
	} else if (*clnt_info.e_domain != '\0') {
		user = smb_session_dup_user(sr->session, clnt_info.e_domain,
		    clnt_info.e_username);
	} else {
		need_lookup = B_TRUE;
	}

	if (user != NULL) {
		sr->user_cr = user->u_cred;
		sr->smb_uid = user->u_uid;
		sr->uid_user = user;

		smb_mfree(buf);

		return ((user->u_flags & SMB_USER_FLAG_GUEST)
		    ? SMB_AUTH_GUEST : SMB_AUTH_USER);
	}

	clnt_info.logon_level = NETR_NETWORK_LOGON;
	clnt_info.domain = sinfo->ssi_domain;
	clnt_info.username = sinfo->ssi_user;
	clnt_info.workstation = sr->session->workstation;
	clnt_info.ipaddr = sr->session->ipaddr;
	clnt_info.local_ipaddr = sr->session->local_ipaddr;
	clnt_info.challenge_key.challenge_key_val =
	    sr->session->challenge_key;
	clnt_info.challenge_key.challenge_key_len =
	    sr->session->challenge_len;
	clnt_info.nt_password.nt_password_val = sinfo->ssi_cspwd;
	clnt_info.nt_password.nt_password_len = sinfo->ssi_cspwlen;
	clnt_info.lm_password.lm_password_val = sinfo->ssi_cipwd;
	clnt_info.lm_password.lm_password_len = sinfo->ssi_cipwlen;
	clnt_info.native_os = sr->session->native_os;
	clnt_info.native_lm = smbnative_lm_value(sinfo->ssi_native_lm);
	clnt_info.local_port = sr->session->s_local_port;

	DTRACE_PROBE1(smb__sessionsetup__clntinfo, netr_client_t *,
	    &clnt_info);

	usr_token = smb_get_token(&clnt_info);

	smb_mfree(buf);

	if (usr_token == NULL) {
		smbsr_error(sr, 0, ERRSRV, ERRbadpw);
		return (SMB_AUTH_FAILED);
	}

	if (need_lookup) {
		user = smb_session_dup_user(sr->session,
		    usr_token->tkn_domain_name, usr_token->tkn_account_name);

		if (user != NULL) {
			sr->user_cr = user->u_cred;
			sr->smb_uid = user->u_uid;
			sr->uid_user = user;

			smb_token_free(usr_token);
			return ((user->u_flags & SMB_USER_FLAG_GUEST)
			    ? SMB_AUTH_GUEST : SMB_AUTH_USER);
		}
	}

	if (usr_token->tkn_session_key) {
		*session_key = kmem_alloc(sizeof (smb_session_key_t),
		    KM_SLEEP);
		(void) memcpy(*session_key, usr_token->tkn_session_key,
		    sizeof (smb_session_key_t));
	}

	if ((cr = smb_cred_create(usr_token, &privileges)) != NULL) {
		user = smb_user_login(sr->session, cr,
		    usr_token->tkn_domain_name,
		    usr_token->tkn_account_name,
		    usr_token->tkn_flags,
		    privileges,
		    usr_token->tkn_audit_sid);

		smb_cred_rele(user->u_cred);
		if (user->u_privcred)
			smb_cred_rele(user->u_privcred);
	}

	smb_token_free(usr_token);

	if (user == NULL) {
		if (*session_key)
			kmem_free(*session_key, sizeof (smb_session_key_t));
		smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_HANDLE);
		return (SMB_AUTH_FAILED);
	}

	sr->user_cr = user->u_cred;
	sr->smb_uid = user->u_uid;
	sr->uid_user = user;

	return ((user->u_flags & SMB_USER_FLAG_GUEST)
	    ? SMB_AUTH_GUEST : SMB_AUTH_USER);
}
コード例 #2
0
ファイル: smb_authenticate.c プロジェクト: bahamas10/openzfs
/*
 * After a successful authentication, ask the authsvc to
 * send us the authentication token.
 */
static uint32_t
smb_auth_get_token(smb_request_t *sr)
{
	smb_lsa_msg_hdr_t msg_hdr;
	XDR		xdrs;
	smb_user_t	*user = sr->uid_user;
	smb_token_t	*token = NULL;
	cred_t		*cr = NULL;
	void		*rbuf = NULL;
	uint32_t	rlen = 0;
	uint32_t	privileges;
	uint32_t	status;
	int		rc;
	bool_t		ok;

	msg_hdr.lmh_msgtype = LSA_MTYPE_GETTOK;
	msg_hdr.lmh_msglen = 0;

	status = smb_authsock_sendrecv(user, &msg_hdr, NULL, &rbuf);
	if (status != 0)
		goto errout;

	rlen = msg_hdr.lmh_msglen;
	switch (msg_hdr.lmh_msgtype) {

	case LSA_MTYPE_TOKEN:
		status = 0;
		break;

	case LSA_MTYPE_ERROR:
		if (rlen == sizeof (smb_lsa_eresp_t)) {
			smb_lsa_eresp_t *ler = rbuf;
			status = ler->ler_ntstatus;
			goto errout;
		}
		/* FALLTHROUGH */

	default:
		status = NT_STATUS_INTERNAL_ERROR;
		goto errout;
	}

	/*
	 * Authenticated.  Decode the LSA_MTYPE_TOKEN.
	 */
	xdrmem_create(&xdrs, rbuf, rlen, XDR_DECODE);
	token = kmem_zalloc(sizeof (smb_token_t), KM_SLEEP);
	ok = smb_token_xdr(&xdrs, token);
	xdr_destroy(&xdrs);
	if (!ok) {
		status = RPC_NT_BAD_STUB_DATA;
		goto errout;
	}
	kmem_free(rbuf, rlen);
	rbuf = NULL;

	/*
	 * Setup the logon object.
	 */
	cr = smb_cred_create(token);
	if (cr == NULL)
		goto errout;
	privileges = smb_priv_xlate(token);
	(void) smb_user_logon(user, cr,
	    token->tkn_domain_name, token->tkn_account_name,
	    token->tkn_flags, privileges, token->tkn_audit_sid);
	crfree(cr);

	/*
	 * Save the session key, and (maybe) enable signing,
	 * but only for real logon (not ANON or GUEST).
	 */
	if ((token->tkn_flags & (SMB_ATF_GUEST | SMB_ATF_ANON)) == 0) {
		if (sr->session->dialect >= SMB_VERS_2_BASE) {
			rc = smb2_sign_begin(sr, token);
		} else {
			rc = smb_sign_begin(sr, token);
		}
		if (rc != 0) {
			status = NT_STATUS_INTERNAL_ERROR;
			goto errout;
		}
	}

	smb_token_free(token);

	sr->user_cr = user->u_cred;
	return (0);

errout:
	if (rbuf != NULL)
		kmem_free(rbuf, rlen);
	if (token != NULL)
		smb_token_free(token);
	return (status);
}