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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Active Directory Setup RPC interface used by Windows 2000. 28 */ 29 30 #include <synch.h> 31 #include <strings.h> 32 #include <stdlib.h> 33 #include <netdb.h> 34 35 #include <smbsrv/libsmb.h> 36 #include <smbsrv/libmlrpc.h> 37 #include <smbsrv/libmlsvc.h> 38 #include <smbsrv/mlsvc_util.h> 39 #include <smbsrv/ndl/dssetup.ndl> 40 #include <smbsrv/ntstatus.h> 41 #include <smbsrv/smbinfo.h> 42 #include <smbsrv/nmpipes.h> 43 44 int dssetup_get_domain_info(ds_primary_domain_info_t *); 45 46 static int dssetup_DsRoleGetPrimaryDomainInfo(void *, ndr_xa_t *); 47 static uint32_t dssetup_member_server(ds_primary_domain_info_t *, ndr_xa_t *); 48 static uint32_t dssetup_standalone_server(ds_primary_domain_info_t *, 49 ndr_xa_t *); 50 51 static mlrpc_stub_table_t dssetup_stub_table[] = { 52 { dssetup_DsRoleGetPrimaryDomainInfo, 53 DSSETUP_OPNUM_DsRoleGetPrimaryDomainInfo }, 54 {0} 55 }; 56 57 static mlrpc_service_t dssetup_service = { 58 "DSSETUP", /* name */ 59 "Active Directory Setup", /* desc */ 60 "\\lsarpc", /* endpoint */ 61 PIPE_LSASS, /* sec_addr_port */ 62 "3919286a-b10c-11d0-9ba800c04fd92ef5", 0, /* abstract */ 63 "8a885d04-1ceb-11c9-9fe808002b104860", 2, /* transfer */ 64 0, /* no bind_instance_size */ 65 0, /* no bind_req() */ 66 0, /* no unbind_and_close() */ 67 0, /* use generic_call_stub() */ 68 &TYPEINFO(dssetup_interface), /* interface ti */ 69 dssetup_stub_table /* stub_table */ 70 }; 71 72 static ds_primary_domain_info_t ds_info; 73 static mutex_t ds_info_mtx; 74 75 /* 76 * dssetup_initialize 77 * 78 * This function registers the DSSETUP interface with the RPC runtime 79 * library. It must be called in order to use either the client side 80 * or the server side functions. 81 */ 82 void 83 dssetup_initialize(void) 84 { 85 dssetup_clear_domain_info(); 86 (void) mlrpc_register_service(&dssetup_service); 87 } 88 89 void 90 dssetup_clear_domain_info(void) 91 { 92 (void) mutex_lock(&ds_info_mtx); 93 94 free(ds_info.nt_domain); 95 free(ds_info.dns_domain); 96 free(ds_info.forest); 97 bzero(&ds_info, sizeof (ds_primary_domain_info_t)); 98 99 (void) mutex_unlock(&ds_info_mtx); 100 } 101 102 /* 103 * Request for machine role and primary domain information. 104 */ 105 static int 106 dssetup_DsRoleGetPrimaryDomainInfo(void *arg, ndr_xa_t *mxa) 107 { 108 dssetup_DsRoleGetPrimaryDomainInfo_t *param = arg; 109 dssetup_GetPrimaryDomainInfo_t *info; 110 ds_primary_domain_info_t *info1; 111 uint32_t status; 112 int security_mode; 113 114 info = MLRPC_HEAP_MALLOC(mxa, sizeof (dssetup_GetPrimaryDomainInfo_t)); 115 if (info == NULL) { 116 status = NT_STATUS_NO_MEMORY; 117 } else if (param->level != DS_ROLE_BASIC_INFORMATION) { 118 status = NT_STATUS_INVALID_LEVEL; 119 } else { 120 info->switch_value = param->level; 121 info1 = &info->ru.info1; 122 123 security_mode = smb_config_get_secmode(); 124 125 if (security_mode == SMB_SECMODE_DOMAIN) 126 status = dssetup_member_server(info1, mxa); 127 else 128 status = dssetup_standalone_server(info1, mxa); 129 } 130 131 if (status != NT_STATUS_SUCCESS) { 132 bzero(param, sizeof (dssetup_DsRoleGetPrimaryDomainInfo_t)); 133 param->status = NT_SC_ERROR(status); 134 } else { 135 param->info = info; 136 param->status = NT_STATUS_SUCCESS; 137 } 138 139 return (MLRPC_DRC_OK); 140 } 141 142 /* 143 * When the machine role is domain member: 144 * nt_domain must contain the NetBIOS domain name 145 * dns_domain must contain the DNS domain name (cannot be NULL) 146 * forest must contain the forest name (cannot be NULL) 147 * 148 * If DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT is set in flags, the domain_guid 149 * must contain the domain UUID. Otherwise domain_guid is ignored. 150 */ 151 static uint32_t 152 dssetup_member_server(ds_primary_domain_info_t *info, ndr_xa_t *mxa) 153 { 154 char dns_domain[MAXHOSTNAMELEN]; 155 char nt_domain[MAXHOSTNAMELEN]; 156 157 (void) mutex_lock(&ds_info_mtx); 158 159 if ((ds_info.flags & DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT) == 0) { 160 /* 161 * If we don't have the domain GUID, try to get it from a 162 * domain controller. Otherwise, use local configuration. 163 */ 164 free(ds_info.nt_domain); 165 free(ds_info.dns_domain); 166 free(ds_info.forest); 167 (void) dssetup_get_domain_info(&ds_info); 168 } 169 170 if (ds_info.flags & DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT) { 171 info->flags = DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT; 172 info->nt_domain = MLRPC_HEAP_STRSAVE(mxa, 173 (char *)ds_info.nt_domain); 174 info->dns_domain = MLRPC_HEAP_STRSAVE(mxa, 175 (char *)ds_info.dns_domain); 176 info->forest = MLRPC_HEAP_STRSAVE(mxa, (char *)ds_info.forest); 177 bcopy(&ds_info.domain_guid, &info->domain_guid, 178 sizeof (ndr_uuid_t)); 179 } else { 180 if (smb_getdomainname(nt_domain, MAXHOSTNAMELEN) != 0) { 181 (void) mutex_unlock(&ds_info_mtx); 182 return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 183 } 184 185 if (smb_getfqdomainname(dns_domain, MAXHOSTNAMELEN) != 0) { 186 (void) mutex_unlock(&ds_info_mtx); 187 return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 188 } 189 190 (void) utf8_strlwr(dns_domain); 191 192 info->flags = 0; 193 info->nt_domain = MLRPC_HEAP_STRSAVE(mxa, nt_domain); 194 info->dns_domain = MLRPC_HEAP_STRSAVE(mxa, dns_domain); 195 info->forest = MLRPC_HEAP_STRSAVE(mxa, dns_domain); 196 bzero(&info->domain_guid, sizeof (ndr_uuid_t)); 197 } 198 199 (void) mutex_unlock(&ds_info_mtx); 200 201 if (info->nt_domain == NULL || 202 info->dns_domain == NULL || 203 info->forest == NULL) 204 return (NT_STATUS_NO_MEMORY); 205 206 info->role = DS_ROLE_MEMBER_SERVER; 207 return (NT_STATUS_SUCCESS); 208 } 209 210 /* 211 * When the machine role is standalone: 212 * nt_domain must contain the NetBIOS workgroup name 213 * dns_domain must be NULL 214 * forest must be NULL 215 * 216 * We don't maintain a domain GUID. When DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT 217 * is not set in flags, domain_guid is ignored. 218 */ 219 static uint32_t 220 dssetup_standalone_server(ds_primary_domain_info_t *info, ndr_xa_t *mxa) 221 { 222 char nt_domain[MAXHOSTNAMELEN]; 223 224 if (smb_getdomainname(nt_domain, MAXHOSTNAMELEN) != 0) 225 return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 226 227 info->nt_domain = MLRPC_HEAP_STRSAVE(mxa, nt_domain); 228 if (info->nt_domain == NULL) 229 return (NT_STATUS_NO_MEMORY); 230 231 info->role = DS_ROLE_STANDALONE_SERVER; 232 info->flags = 0; 233 info->dns_domain = NULL; 234 info->forest = NULL; 235 bzero(&info->domain_guid, sizeof (ndr_uuid_t)); 236 return (NT_STATUS_SUCCESS); 237 } 238