xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c (revision 8474:7803efd2fa77)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
215331Samw /*
22*8474SJose.Borrego@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
235331Samw  * Use is subject to license terms.
245331Samw  */
255331Samw 
265331Samw /*
275331Samw  * Utility functions to support the RPC interface library.
285331Samw  */
295331Samw 
305331Samw #include <stdio.h>
315331Samw #include <stdarg.h>
325331Samw #include <strings.h>
335331Samw #include <unistd.h>
345331Samw #include <netdb.h>
355331Samw #include <stdlib.h>
365331Samw #include <sys/time.h>
375331Samw #include <sys/systm.h>
385331Samw 
395331Samw #include <smbsrv/libsmb.h>
405331Samw #include <smbsrv/libsmbrdr.h>
415331Samw #include <smbsrv/libsmbns.h>
425331Samw #include <smbsrv/libmlsvc.h>
435331Samw #include <smbsrv/smbinfo.h>
448334SJose.Borrego@Sun.COM #include <lsalib.h>
458334SJose.Borrego@Sun.COM #include <samlib.h>
468334SJose.Borrego@Sun.COM #include <smbsrv/netrauth.h>
475331Samw 
485772Sas200622 /* Domain join support (using MS-RPC) */
495772Sas200622 static boolean_t mlsvc_ntjoin_support = B_FALSE;
505772Sas200622 
515331Samw extern int netr_open(char *, char *, mlsvc_handle_t *);
525331Samw extern int netr_close(mlsvc_handle_t *);
535331Samw extern DWORD netlogon_auth(char *, mlsvc_handle_t *, DWORD);
545331Samw extern int mlsvc_user_getauth(char *, char *, smb_auth_info_t *);
555331Samw 
565331Samw /*
575331Samw  * mlsvc_lookup_name
585331Samw  *
595772Sas200622  * This is just a wrapper for lsa_lookup_name.
605331Samw  *
615772Sas200622  * The memory for the sid is allocated using malloc so the caller should
625772Sas200622  * call free when it is no longer required.
635331Samw  */
645772Sas200622 uint32_t
656432Sas200622 mlsvc_lookup_name(char *account, smb_sid_t **sid, uint16_t *sid_type)
665331Samw {
675772Sas200622 	smb_userinfo_t *ainfo;
685772Sas200622 	uint32_t status;
695331Samw 
705772Sas200622 	if ((ainfo = mlsvc_alloc_user_info()) == NULL)
715772Sas200622 		return (NT_STATUS_NO_MEMORY);
725331Samw 
738334SJose.Borrego@Sun.COM 	status = lsa_lookup_name(account, *sid_type, ainfo);
745772Sas200622 	if (status == NT_STATUS_SUCCESS) {
755772Sas200622 		*sid = ainfo->user_sid;
765772Sas200622 		ainfo->user_sid = NULL;
775772Sas200622 		*sid_type = ainfo->sid_name_use;
785772Sas200622 	}
795331Samw 
805772Sas200622 	mlsvc_free_user_info(ainfo);
815772Sas200622 	return (status);
825331Samw }
835331Samw 
845331Samw /*
855331Samw  * mlsvc_lookup_sid
865331Samw  *
875772Sas200622  * This is just a wrapper for lsa_lookup_sid.
885772Sas200622  *
895772Sas200622  * The allocated memory for the returned name must be freed by caller upon
905772Sas200622  * successful return.
915331Samw  */
925772Sas200622 uint32_t
936432Sas200622 mlsvc_lookup_sid(smb_sid_t *sid, char **name)
945331Samw {
955772Sas200622 	smb_userinfo_t *ainfo;
965772Sas200622 	uint32_t status;
975772Sas200622 	int namelen;
985331Samw 
995772Sas200622 	if ((ainfo = mlsvc_alloc_user_info()) == NULL)
1005772Sas200622 		return (NT_STATUS_NO_MEMORY);
1015331Samw 
1025772Sas200622 	status = lsa_lookup_sid(sid, ainfo);
1035772Sas200622 	if (status == NT_STATUS_SUCCESS) {
1045772Sas200622 		namelen = strlen(ainfo->domain_name) + strlen(ainfo->name) + 2;
1055772Sas200622 		if ((*name = malloc(namelen)) == NULL) {
1065772Sas200622 			mlsvc_free_user_info(ainfo);
1075772Sas200622 			return (NT_STATUS_NO_MEMORY);
1085331Samw 		}
1095772Sas200622 		(void) snprintf(*name, namelen, "%s\\%s",
1105772Sas200622 		    ainfo->domain_name, ainfo->name);
1115331Samw 	}
1125331Samw 
1135772Sas200622 	mlsvc_free_user_info(ainfo);
1145772Sas200622 	return (status);
1155331Samw }
1165331Samw 
1175331Samw /*
1185331Samw  * mlsvc_alloc_user_info
1195331Samw  *
1205331Samw  * Allocate a user_info structure and set the contents to zero. A
1215331Samw  * pointer to the user_info structure is returned.
1225331Samw  */
1235331Samw smb_userinfo_t *
1245331Samw mlsvc_alloc_user_info(void)
1255331Samw {
1265331Samw 	smb_userinfo_t *user_info;
1275331Samw 
1285331Samw 	user_info = (smb_userinfo_t *)malloc(sizeof (smb_userinfo_t));
1295331Samw 	if (user_info == NULL)
1305331Samw 		return (NULL);
1315331Samw 
1325331Samw 	bzero(user_info, sizeof (smb_userinfo_t));
1335331Samw 	return (user_info);
1345331Samw }
1355331Samw 
1365331Samw /*
1375331Samw  * mlsvc_free_user_info
1385331Samw  *
1395331Samw  * Free a user_info structure. This function ensures that the contents
1405331Samw  * of the user_info are freed as well as the user_info itself.
1415331Samw  */
1425331Samw void
1435331Samw mlsvc_free_user_info(smb_userinfo_t *user_info)
1445331Samw {
1455331Samw 	if (user_info) {
1465331Samw 		mlsvc_release_user_info(user_info);
1475331Samw 		free(user_info);
1485331Samw 	}
1495331Samw }
1505331Samw 
1515331Samw /*
1525331Samw  * mlsvc_release_user_info
1535331Samw  *
1545331Samw  * Release the contents of a user_info structure and zero out the
1555331Samw  * elements but do not free the user_info structure itself. This
1565331Samw  * function cleans out the structure so that it can be reused without
1575331Samw  * worrying about stale contents.
1585331Samw  */
1595331Samw void
1605331Samw mlsvc_release_user_info(smb_userinfo_t *user_info)
1615331Samw {
1625331Samw 	int i;
1635331Samw 
1645331Samw 	if (user_info == NULL)
1655331Samw 		return;
1665331Samw 
1675331Samw 	free(user_info->name);
1685331Samw 	free(user_info->domain_sid);
1695331Samw 	free(user_info->domain_name);
1705331Samw 	free(user_info->groups);
1715331Samw 
1725331Samw 	if (user_info->n_other_grps) {
1735331Samw 		for (i = 0; i < user_info->n_other_grps; i++)
1745331Samw 			free(user_info->other_grps[i].sid);
1755331Samw 
1765331Samw 		free(user_info->other_grps);
1775331Samw 	}
1785331Samw 
1796849Sjb150015 	free(user_info->session_key);
1805331Samw 	free(user_info->user_sid);
1815331Samw 	free(user_info->pgrp_sid);
1825331Samw 	bzero(user_info, sizeof (smb_userinfo_t));
1835331Samw }
1845331Samw 
1855331Samw /*
1865331Samw  * mlsvc_setadmin_user_info
1875331Samw  *
1885331Samw  * Determines if the given user is the domain Administrator or a
1895331Samw  * member of Domain Admins or Administrators group and set the
1905331Samw  * user_info->flags accordingly.
1915331Samw  */
1925331Samw void
1935331Samw mlsvc_setadmin_user_info(smb_userinfo_t *user_info)
1945331Samw {
1955331Samw 	nt_domain_t *domain;
1965772Sas200622 	smb_group_t grp;
1975772Sas200622 	int rc, i;
1985331Samw 
1995331Samw 	if ((domain = nt_domain_lookupbytype(NT_DOMAIN_PRIMARY)) == NULL)
2005331Samw 		return;
2015331Samw 
2026432Sas200622 	if (!smb_sid_cmp((smb_sid_t *)user_info->domain_sid, domain->sid))
2035331Samw 		return;
2045331Samw 
2055331Samw 	if (user_info->rid == DOMAIN_USER_RID_ADMIN)
2065331Samw 		user_info->flags |= SMB_UINFO_FLAG_DADMIN;
2075331Samw 	else if (user_info->primary_group_rid == DOMAIN_GROUP_RID_ADMINS)
2085331Samw 		user_info->flags |= SMB_UINFO_FLAG_DADMIN;
2095331Samw 	else {
2105331Samw 		for (i = 0; i < user_info->n_groups; i++)
2115331Samw 			if (user_info->groups[i].rid == DOMAIN_GROUP_RID_ADMINS)
2125331Samw 				user_info->flags |= SMB_UINFO_FLAG_DADMIN;
2135331Samw 	}
2145331Samw 
2155772Sas200622 	rc = smb_lgrp_getbyname("Administrators", &grp);
2165772Sas200622 	if (rc == SMB_LGRP_SUCCESS) {
2175772Sas200622 		if (smb_lgrp_is_member(&grp, user_info->user_sid))
2185331Samw 			user_info->flags |= SMB_UINFO_FLAG_LADMIN;
2195772Sas200622 		smb_lgrp_free(&grp);
2205331Samw 	}
2215331Samw }
2225331Samw 
2236139Sjb150015 DWORD
2246139Sjb150015 mlsvc_netlogon(char *server, char *domain)
2256139Sjb150015 {
2266139Sjb150015 	mlsvc_handle_t netr_handle;
2276139Sjb150015 	DWORD status;
2286139Sjb150015 
2296139Sjb150015 	if (netr_open(server, domain, &netr_handle) == 0) {
2306139Sjb150015 		status = netlogon_auth(server, &netr_handle,
2316139Sjb150015 		    NETR_FLG_INIT);
2326139Sjb150015 		(void) netr_close(&netr_handle);
2336139Sjb150015 	} else {
2346139Sjb150015 		status = NT_STATUS_OPEN_FAILED;
2356139Sjb150015 	}
2366139Sjb150015 
2376139Sjb150015 	return (status);
2386139Sjb150015 }
2396139Sjb150015 
2405331Samw /*
2415521Sas200622  * mlsvc_join
2425331Samw  *
2435331Samw  * Returns NT status codes.
2445331Samw  */
2455331Samw DWORD
2468334SJose.Borrego@Sun.COM mlsvc_join(smb_domain_t *dinfo, char *user, char *plain_text)
2475331Samw {
2485331Samw 	smb_auth_info_t auth;
2495331Samw 	int erc;
2505331Samw 	DWORD status;
2518334SJose.Borrego@Sun.COM 	char machine_passwd[NETR_MACHINE_ACCT_PASSWD_MAX];
2525331Samw 
2535331Samw 	machine_passwd[0] = '\0';
2545331Samw 
2555331Samw 	/*
2565331Samw 	 * Ensure that the domain name is uppercase.
2575331Samw 	 */
2588334SJose.Borrego@Sun.COM 	(void) utf8_strupr(dinfo->d_nbdomain);
2595331Samw 
2608334SJose.Borrego@Sun.COM 	erc = mlsvc_logon(dinfo->d_dc, dinfo->d_nbdomain, user);
2615331Samw 
2625331Samw 	if (erc == AUTH_USER_GRANT) {
2635772Sas200622 		if (mlsvc_ntjoin_support == B_FALSE) {
2645331Samw 
2658334SJose.Borrego@Sun.COM 			if (smb_ads_join(dinfo->d_fqdomain, user, plain_text,
2665772Sas200622 			    machine_passwd, sizeof (machine_passwd))
2677052Samw 			    == SMB_ADJOIN_SUCCESS)
2685331Samw 				status = NT_STATUS_SUCCESS;
2695521Sas200622 			else
2705331Samw 				status = NT_STATUS_UNSUCCESSFUL;
2715331Samw 		} else {
2728334SJose.Borrego@Sun.COM 			if (mlsvc_user_getauth(dinfo->d_dc, user, &auth)
2735331Samw 			    != 0) {
2745331Samw 				status = NT_STATUS_INVALID_PARAMETER;
2755331Samw 				return (status);
2765331Samw 			}
2775331Samw 
2788334SJose.Borrego@Sun.COM 			status = sam_create_trust_account(dinfo->d_dc,
2798334SJose.Borrego@Sun.COM 			    dinfo->d_nbdomain, &auth);
2805331Samw 			if (status == NT_STATUS_SUCCESS) {
2817961SNatalie.Li@Sun.COM 				(void) smb_getnetbiosname(machine_passwd,
2827961SNatalie.Li@Sun.COM 				    sizeof (machine_passwd));
2835331Samw 				(void) utf8_strlwr(machine_passwd);
2845331Samw 			}
2855331Samw 		}
2865331Samw 
2875331Samw 		if (status == NT_STATUS_SUCCESS) {
2888334SJose.Borrego@Sun.COM 			erc = smb_setdomainprops(NULL, dinfo->d_dc,
2895772Sas200622 			    machine_passwd);
2906139Sjb150015 			if (erc != 0)
2915331Samw 				return (NT_STATUS_UNSUCCESSFUL);
2925331Samw 
2938334SJose.Borrego@Sun.COM 			status = mlsvc_netlogon(dinfo->d_dc, dinfo->d_nbdomain);
2945331Samw 		}
2955331Samw 	} else {
2965331Samw 		status = NT_STATUS_LOGON_FAILURE;
2975331Samw 	}
2985331Samw 
2995331Samw 	return (status);
3005331Samw }
301