Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*
     27  * Utility functions to support the RPC interface library.
     28  */
     29 
     30 #include <stdio.h>
     31 #include <stdarg.h>
     32 #include <strings.h>
     33 #include <unistd.h>
     34 #include <netdb.h>
     35 #include <stdlib.h>
     36 #include <sys/time.h>
     37 #include <sys/systm.h>
     38 #include <syslog.h>
     39 
     40 #include <smbsrv/libsmb.h>
     41 #include <smbsrv/libsmbns.h>
     42 #include <smbsrv/libmlsvc.h>
     43 #include <smbsrv/libsmbrdr.h>
     44 #include <smbsrv/smbinfo.h>
     45 #include <lsalib.h>
     46 #include <samlib.h>
     47 #include <smbsrv/netrauth.h>
     48 
     49 /* Domain join support (using MS-RPC) */
     50 static boolean_t mlsvc_ntjoin_support = B_FALSE;
     51 
     52 extern int netr_open(char *, char *, mlsvc_handle_t *);
     53 extern int netr_close(mlsvc_handle_t *);
     54 extern DWORD netlogon_auth(char *, mlsvc_handle_t *, DWORD);
     55 
     56 /*
     57  * mlsvc_lookup_name
     58  *
     59  * This is just a wrapper for lsa_lookup_name.
     60  *
     61  * The memory for the sid is allocated using malloc so the caller should
     62  * call free when it is no longer required.
     63  */
     64 uint32_t
     65 mlsvc_lookup_name(char *name, smb_sid_t **sid, uint16_t *sid_type)
     66 {
     67 	smb_account_t account;
     68 	uint32_t status;
     69 
     70 	status = lsa_lookup_name(name, *sid_type, &account);
     71 	if (status == NT_STATUS_SUCCESS) {
     72 		*sid = account.a_sid;
     73 		account.a_sid = NULL;
     74 		*sid_type = account.a_type;
     75 		smb_account_free(&account);
     76 	}
     77 
     78 	return (status);
     79 }
     80 
     81 /*
     82  * mlsvc_lookup_sid
     83  *
     84  * This is just a wrapper for lsa_lookup_sid.
     85  *
     86  * The allocated memory for the returned name must be freed by caller upon
     87  * successful return.
     88  */
     89 uint32_t
     90 mlsvc_lookup_sid(smb_sid_t *sid, char **name)
     91 {
     92 	smb_account_t ainfo;
     93 	uint32_t status;
     94 	int namelen;
     95 
     96 	if ((status = lsa_lookup_sid(sid, &ainfo)) == NT_STATUS_SUCCESS) {
     97 		namelen = strlen(ainfo.a_domain) + strlen(ainfo.a_name) + 2;
     98 		if ((*name = malloc(namelen)) != NULL)
     99 			(void) snprintf(*name, namelen, "%s\\%s",
    100 			    ainfo.a_domain, ainfo.a_name);
    101 		else
    102 			status = NT_STATUS_NO_MEMORY;
    103 
    104 		smb_account_free(&ainfo);
    105 	}
    106 
    107 	return (status);
    108 }
    109 
    110 DWORD
    111 mlsvc_netlogon(char *server, char *domain)
    112 {
    113 	mlsvc_handle_t netr_handle;
    114 	DWORD status;
    115 
    116 	if (netr_open(server, domain, &netr_handle) == 0) {
    117 		if ((status = netlogon_auth(server, &netr_handle,
    118 		    NETR_FLG_INIT)) != NT_STATUS_SUCCESS)
    119 			syslog(LOG_NOTICE, "Failed to establish NETLOGON "
    120 			    "credential chain");
    121 		(void) netr_close(&netr_handle);
    122 	} else {
    123 		status = NT_STATUS_OPEN_FAILED;
    124 	}
    125 
    126 	return (status);
    127 }
    128 
    129 /*
    130  * Joins the specified domain by creating a machine account on
    131  * the selected domain controller.
    132  *
    133  * Disconnect any existing connection with the domain controller.
    134  * This will ensure that no stale connection will be used, it will
    135  * also pickup any configuration changes in either side by trying
    136  * to establish a new connection.
    137  *
    138  * Returns NT status codes.
    139  */
    140 DWORD
    141 mlsvc_join(smb_domainex_t *dxi, char *user, char *plain_text)
    142 {
    143 	int erc;
    144 	DWORD status;
    145 	char machine_passwd[NETR_MACHINE_ACCT_PASSWD_MAX];
    146 	smb_adjoin_status_t err;
    147 	smb_domain_t *domain;
    148 
    149 	machine_passwd[0] = '\0';
    150 
    151 	domain = &dxi->d_primary;
    152 
    153 	mlsvc_disconnect(dxi->d_dc);
    154 
    155 	erc = smbrdr_logon(dxi->d_dc, domain->di_nbname, user);
    156 
    157 	if (erc == AUTH_USER_GRANT) {
    158 		if (mlsvc_ntjoin_support == B_FALSE) {
    159 
    160 			if ((err = smb_ads_join(domain->di_fqname, user,
    161 			    plain_text, machine_passwd,
    162 			    sizeof (machine_passwd))) == SMB_ADJOIN_SUCCESS) {
    163 				status = NT_STATUS_SUCCESS;
    164 			} else {
    165 				smb_ads_join_errmsg(err);
    166 				status = NT_STATUS_UNSUCCESSFUL;
    167 			}
    168 		} else {
    169 
    170 			status = sam_create_trust_account(dxi->d_dc,
    171 			    domain->di_nbname);
    172 			if (status == NT_STATUS_SUCCESS) {
    173 				(void) smb_getnetbiosname(machine_passwd,
    174 				    sizeof (machine_passwd));
    175 				(void) smb_strlwr(machine_passwd);
    176 			}
    177 		}
    178 
    179 		if (status == NT_STATUS_SUCCESS) {
    180 			erc = smb_setdomainprops(NULL, dxi->d_dc,
    181 			    machine_passwd);
    182 			if (erc != 0) {
    183 				syslog(LOG_NOTICE, "Failed to update CIFS "
    184 				    "configuration");
    185 				return (NT_STATUS_UNSUCCESSFUL);
    186 			}
    187 
    188 			status = mlsvc_netlogon(dxi->d_dc, domain->di_nbname);
    189 		}
    190 	} else {
    191 		status = NT_STATUS_LOGON_FAILURE;
    192 	}
    193 
    194 	return (status);
    195 }
    196 
    197 int
    198 mlsvc_ping(const char *server)
    199 {
    200 	return (smbrdr_echo(server));
    201 }
    202 
    203 void
    204 mlsvc_disconnect(const char *server)
    205 {
    206 	smbrdr_disconnect(server);
    207 }
    208