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 /* 225772Sas200622 * Copyright 2008 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> 44*8334SJose.Borrego@Sun.COM #include <lsalib.h> 45*8334SJose.Borrego@Sun.COM #include <samlib.h> 46*8334SJose.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 * Compare the supplied domain name with the local hostname. 585331Samw * We need to deal with both server names and fully-qualified 595331Samw * domain names. 605331Samw * 615331Samw * Returns: 625331Samw * 0 The specified domain is not the local domain, 635331Samw * 1 The Specified domain is the local domain. 645331Samw * -1 Invalid parameter or unable to get the local 655331Samw * system information. 665331Samw */ 675331Samw int 685331Samw mlsvc_is_local_domain(const char *domain) 695331Samw { 705331Samw char hostname[MAXHOSTNAMELEN]; 715331Samw int rc; 725331Samw 735772Sas200622 if (smb_config_get_secmode() == SMB_SECMODE_WORKGRP) 745772Sas200622 return (1); 755772Sas200622 765331Samw if (strchr(domain, '.') != NULL) 775331Samw rc = smb_getfqhostname(hostname, MAXHOSTNAMELEN); 787961SNatalie.Li@Sun.COM else { 797961SNatalie.Li@Sun.COM if (strlen(domain) < NETBIOS_NAME_SZ) 807961SNatalie.Li@Sun.COM rc = smb_getnetbiosname(hostname, MAXHOSTNAMELEN); 817961SNatalie.Li@Sun.COM else 827961SNatalie.Li@Sun.COM rc = smb_gethostname(hostname, MAXHOSTNAMELEN, 1); 837961SNatalie.Li@Sun.COM } 845331Samw 855331Samw if (rc != 0) 865331Samw return (-1); 875331Samw 885772Sas200622 if (strcasecmp(domain, hostname) == 0) 895331Samw return (1); 905331Samw 915331Samw return (0); 925331Samw } 935331Samw 945331Samw /* 955331Samw * mlsvc_lookup_name 965331Samw * 975772Sas200622 * This is just a wrapper for lsa_lookup_name. 985331Samw * 995772Sas200622 * The memory for the sid is allocated using malloc so the caller should 1005772Sas200622 * call free when it is no longer required. 1015331Samw */ 1025772Sas200622 uint32_t 1036432Sas200622 mlsvc_lookup_name(char *account, smb_sid_t **sid, uint16_t *sid_type) 1045331Samw { 1055772Sas200622 smb_userinfo_t *ainfo; 1065772Sas200622 uint32_t status; 1075331Samw 1085772Sas200622 if ((ainfo = mlsvc_alloc_user_info()) == NULL) 1095772Sas200622 return (NT_STATUS_NO_MEMORY); 1105331Samw 111*8334SJose.Borrego@Sun.COM status = lsa_lookup_name(account, *sid_type, ainfo); 1125772Sas200622 if (status == NT_STATUS_SUCCESS) { 1135772Sas200622 *sid = ainfo->user_sid; 1145772Sas200622 ainfo->user_sid = NULL; 1155772Sas200622 *sid_type = ainfo->sid_name_use; 1165772Sas200622 } 1175331Samw 1185772Sas200622 mlsvc_free_user_info(ainfo); 1195772Sas200622 return (status); 1205331Samw } 1215331Samw 1225331Samw /* 1235331Samw * mlsvc_lookup_sid 1245331Samw * 1255772Sas200622 * This is just a wrapper for lsa_lookup_sid. 1265772Sas200622 * 1275772Sas200622 * The allocated memory for the returned name must be freed by caller upon 1285772Sas200622 * successful return. 1295331Samw */ 1305772Sas200622 uint32_t 1316432Sas200622 mlsvc_lookup_sid(smb_sid_t *sid, char **name) 1325331Samw { 1335772Sas200622 smb_userinfo_t *ainfo; 1345772Sas200622 uint32_t status; 1355772Sas200622 int namelen; 1365331Samw 1375772Sas200622 if ((ainfo = mlsvc_alloc_user_info()) == NULL) 1385772Sas200622 return (NT_STATUS_NO_MEMORY); 1395331Samw 1405772Sas200622 status = lsa_lookup_sid(sid, ainfo); 1415772Sas200622 if (status == NT_STATUS_SUCCESS) { 1425772Sas200622 namelen = strlen(ainfo->domain_name) + strlen(ainfo->name) + 2; 1435772Sas200622 if ((*name = malloc(namelen)) == NULL) { 1445772Sas200622 mlsvc_free_user_info(ainfo); 1455772Sas200622 return (NT_STATUS_NO_MEMORY); 1465331Samw } 1475772Sas200622 (void) snprintf(*name, namelen, "%s\\%s", 1485772Sas200622 ainfo->domain_name, ainfo->name); 1495331Samw } 1505331Samw 1515772Sas200622 mlsvc_free_user_info(ainfo); 1525772Sas200622 return (status); 1535331Samw } 1545331Samw 1555331Samw /* 1565331Samw * mlsvc_alloc_user_info 1575331Samw * 1585331Samw * Allocate a user_info structure and set the contents to zero. A 1595331Samw * pointer to the user_info structure is returned. 1605331Samw */ 1615331Samw smb_userinfo_t * 1625331Samw mlsvc_alloc_user_info(void) 1635331Samw { 1645331Samw smb_userinfo_t *user_info; 1655331Samw 1665331Samw user_info = (smb_userinfo_t *)malloc(sizeof (smb_userinfo_t)); 1675331Samw if (user_info == NULL) 1685331Samw return (NULL); 1695331Samw 1705331Samw bzero(user_info, sizeof (smb_userinfo_t)); 1715331Samw return (user_info); 1725331Samw } 1735331Samw 1745331Samw /* 1755331Samw * mlsvc_free_user_info 1765331Samw * 1775331Samw * Free a user_info structure. This function ensures that the contents 1785331Samw * of the user_info are freed as well as the user_info itself. 1795331Samw */ 1805331Samw void 1815331Samw mlsvc_free_user_info(smb_userinfo_t *user_info) 1825331Samw { 1835331Samw if (user_info) { 1845331Samw mlsvc_release_user_info(user_info); 1855331Samw free(user_info); 1865331Samw } 1875331Samw } 1885331Samw 1895331Samw /* 1905331Samw * mlsvc_release_user_info 1915331Samw * 1925331Samw * Release the contents of a user_info structure and zero out the 1935331Samw * elements but do not free the user_info structure itself. This 1945331Samw * function cleans out the structure so that it can be reused without 1955331Samw * worrying about stale contents. 1965331Samw */ 1975331Samw void 1985331Samw mlsvc_release_user_info(smb_userinfo_t *user_info) 1995331Samw { 2005331Samw int i; 2015331Samw 2025331Samw if (user_info == NULL) 2035331Samw return; 2045331Samw 2055331Samw free(user_info->name); 2065331Samw free(user_info->domain_sid); 2075331Samw free(user_info->domain_name); 2085331Samw free(user_info->groups); 2095331Samw 2105331Samw if (user_info->n_other_grps) { 2115331Samw for (i = 0; i < user_info->n_other_grps; i++) 2125331Samw free(user_info->other_grps[i].sid); 2135331Samw 2145331Samw free(user_info->other_grps); 2155331Samw } 2165331Samw 2176849Sjb150015 free(user_info->session_key); 2185331Samw free(user_info->user_sid); 2195331Samw free(user_info->pgrp_sid); 2205331Samw bzero(user_info, sizeof (smb_userinfo_t)); 2215331Samw } 2225331Samw 2235331Samw /* 2245331Samw * mlsvc_setadmin_user_info 2255331Samw * 2265331Samw * Determines if the given user is the domain Administrator or a 2275331Samw * member of Domain Admins or Administrators group and set the 2285331Samw * user_info->flags accordingly. 2295331Samw */ 2305331Samw void 2315331Samw mlsvc_setadmin_user_info(smb_userinfo_t *user_info) 2325331Samw { 2335331Samw nt_domain_t *domain; 2345772Sas200622 smb_group_t grp; 2355772Sas200622 int rc, i; 2365331Samw 2375331Samw if ((domain = nt_domain_lookupbytype(NT_DOMAIN_PRIMARY)) == NULL) 2385331Samw return; 2395331Samw 2406432Sas200622 if (!smb_sid_cmp((smb_sid_t *)user_info->domain_sid, domain->sid)) 2415331Samw return; 2425331Samw 2435331Samw if (user_info->rid == DOMAIN_USER_RID_ADMIN) 2445331Samw user_info->flags |= SMB_UINFO_FLAG_DADMIN; 2455331Samw else if (user_info->primary_group_rid == DOMAIN_GROUP_RID_ADMINS) 2465331Samw user_info->flags |= SMB_UINFO_FLAG_DADMIN; 2475331Samw else { 2485331Samw for (i = 0; i < user_info->n_groups; i++) 2495331Samw if (user_info->groups[i].rid == DOMAIN_GROUP_RID_ADMINS) 2505331Samw user_info->flags |= SMB_UINFO_FLAG_DADMIN; 2515331Samw } 2525331Samw 2535772Sas200622 rc = smb_lgrp_getbyname("Administrators", &grp); 2545772Sas200622 if (rc == SMB_LGRP_SUCCESS) { 2555772Sas200622 if (smb_lgrp_is_member(&grp, user_info->user_sid)) 2565331Samw user_info->flags |= SMB_UINFO_FLAG_LADMIN; 2575772Sas200622 smb_lgrp_free(&grp); 2585331Samw } 2595331Samw } 2605331Samw 2616139Sjb150015 DWORD 2626139Sjb150015 mlsvc_netlogon(char *server, char *domain) 2636139Sjb150015 { 2646139Sjb150015 mlsvc_handle_t netr_handle; 2656139Sjb150015 DWORD status; 2666139Sjb150015 2676139Sjb150015 if (netr_open(server, domain, &netr_handle) == 0) { 2686139Sjb150015 status = netlogon_auth(server, &netr_handle, 2696139Sjb150015 NETR_FLG_INIT); 2706139Sjb150015 (void) netr_close(&netr_handle); 2716139Sjb150015 } else { 2726139Sjb150015 status = NT_STATUS_OPEN_FAILED; 2736139Sjb150015 } 2746139Sjb150015 2756139Sjb150015 return (status); 2766139Sjb150015 } 2776139Sjb150015 2785331Samw /* 2795521Sas200622 * mlsvc_join 2805331Samw * 2815331Samw * Returns NT status codes. 2825331Samw */ 2835331Samw DWORD 284*8334SJose.Borrego@Sun.COM mlsvc_join(smb_domain_t *dinfo, char *user, char *plain_text) 2855331Samw { 2865331Samw smb_auth_info_t auth; 2875331Samw int erc; 2885331Samw DWORD status; 289*8334SJose.Borrego@Sun.COM char machine_passwd[NETR_MACHINE_ACCT_PASSWD_MAX]; 2905331Samw 2915331Samw machine_passwd[0] = '\0'; 2925331Samw 2935331Samw /* 2945331Samw * Ensure that the domain name is uppercase. 2955331Samw */ 296*8334SJose.Borrego@Sun.COM (void) utf8_strupr(dinfo->d_nbdomain); 2975331Samw 298*8334SJose.Borrego@Sun.COM erc = mlsvc_logon(dinfo->d_dc, dinfo->d_nbdomain, user); 2995331Samw 3005331Samw if (erc == AUTH_USER_GRANT) { 3015772Sas200622 if (mlsvc_ntjoin_support == B_FALSE) { 3025331Samw 303*8334SJose.Borrego@Sun.COM if (smb_ads_join(dinfo->d_fqdomain, user, plain_text, 3045772Sas200622 machine_passwd, sizeof (machine_passwd)) 3057052Samw == SMB_ADJOIN_SUCCESS) 3065331Samw status = NT_STATUS_SUCCESS; 3075521Sas200622 else 3085331Samw status = NT_STATUS_UNSUCCESSFUL; 3095331Samw } else { 310*8334SJose.Borrego@Sun.COM if (mlsvc_user_getauth(dinfo->d_dc, user, &auth) 3115331Samw != 0) { 3125331Samw status = NT_STATUS_INVALID_PARAMETER; 3135331Samw return (status); 3145331Samw } 3155331Samw 316*8334SJose.Borrego@Sun.COM status = sam_create_trust_account(dinfo->d_dc, 317*8334SJose.Borrego@Sun.COM dinfo->d_nbdomain, &auth); 3185331Samw if (status == NT_STATUS_SUCCESS) { 3197961SNatalie.Li@Sun.COM (void) smb_getnetbiosname(machine_passwd, 3207961SNatalie.Li@Sun.COM sizeof (machine_passwd)); 3215331Samw (void) utf8_strlwr(machine_passwd); 3225331Samw } 3235331Samw } 3245331Samw 3255331Samw if (status == NT_STATUS_SUCCESS) { 326*8334SJose.Borrego@Sun.COM erc = smb_setdomainprops(NULL, dinfo->d_dc, 3275772Sas200622 machine_passwd); 3286139Sjb150015 if (erc != 0) 3295331Samw return (NT_STATUS_UNSUCCESSFUL); 3305331Samw 331*8334SJose.Borrego@Sun.COM status = mlsvc_netlogon(dinfo->d_dc, dinfo->d_nbdomain); 3325331Samw } 3335331Samw } else { 3345331Samw status = NT_STATUS_LOGON_FAILURE; 3355331Samw } 3365331Samw 3375331Samw return (status); 3385331Samw } 339