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 /* 23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright 2019 Nexenta Systems, Inc. All rights reserved. 25 */ 26 27 /* 28 * LSA lookups 29 */ 30 31 #include <stdio.h> 32 #include <note.h> 33 #include <assert.h> 34 35 #include "idmapd.h" 36 #include "libsmb.h" 37 38 idmap_retcode 39 idmap_lsa_xlate_sid_type(const lsa_account_t *acct, idmap_id_type *ret_type) 40 { 41 switch (acct->a_sidtype) { 42 case SidTypeUser: 43 case SidTypeComputer: 44 case SidTypeDomain: 45 case SidTypeDeletedAccount: 46 case SidTypeUnknown: 47 case SidTypeLabel: 48 *ret_type = IDMAP_USID; 49 return (IDMAP_SUCCESS); 50 case SidTypeGroup: 51 case SidTypeAlias: 52 case SidTypeWellKnownGroup: 53 *ret_type = IDMAP_GSID; 54 return (IDMAP_SUCCESS); 55 case SidTypeNull: 56 case SidTypeInvalid: 57 default: 58 idmapdlog(LOG_WARNING, 59 "LSA lookup: bad type %d for %s@%s", 60 acct->a_sidtype, acct->a_name, acct->a_domain); 61 return (IDMAP_ERR_OTHER); 62 } 63 NOTE(NOTREACHED) 64 } 65 66 /* Given SID, look up name and type */ 67 idmap_retcode 68 lookup_lsa_by_sid( 69 const char *sidprefix, 70 uint32_t rid, 71 char **ret_name, 72 char **ret_domain, 73 idmap_id_type *ret_type) 74 { 75 lsa_account_t acct; 76 char sid[SMB_SID_STRSZ + 1]; 77 idmap_retcode ret; 78 int rc; 79 80 (void) memset(&acct, 0, sizeof (acct)); 81 *ret_name = NULL; 82 *ret_domain = NULL; 83 84 (void) snprintf(sid, sizeof (sid), "%s-%u", sidprefix, rid); 85 86 rc = smb_lookup_lsid(sid, &acct); 87 if (rc != 0) { 88 idmapdlog(LOG_ERR, "Error: SMB lookup SID failed."); 89 idmapdlog(LOG_ERR, 90 "Check SMB service (svc:/network/smb/server)."); 91 idmapdlog(LOG_ERR, 92 "Check connectivity to Active Directory."); 93 94 ret = IDMAP_ERR_OTHER; 95 goto out; 96 } 97 if (acct.a_status == NT_STATUS_NONE_MAPPED) { 98 ret = IDMAP_ERR_NOTFOUND; 99 goto out; 100 } 101 if (acct.a_status != NT_STATUS_SUCCESS) { 102 idmapdlog(LOG_WARNING, 103 "Warning: SMB lookup SID(%s) failed (0x%x)", 104 sid, acct.a_status); 105 /* Fail soft */ 106 ret = IDMAP_ERR_NOTFOUND; 107 goto out; 108 } 109 110 ret = idmap_lsa_xlate_sid_type(&acct, ret_type); 111 if (ret != IDMAP_SUCCESS) 112 goto out; 113 114 *ret_name = strdup(acct.a_name); 115 if (*ret_name == NULL) { 116 ret = IDMAP_ERR_MEMORY; 117 goto out; 118 } 119 120 *ret_domain = strdup(acct.a_domain); 121 if (*ret_domain == NULL) { 122 ret = IDMAP_ERR_MEMORY; 123 goto out; 124 } 125 126 ret = IDMAP_SUCCESS; 127 128 out: 129 if (ret != IDMAP_SUCCESS) { 130 free(*ret_name); 131 *ret_name = NULL; 132 free(*ret_domain); 133 *ret_domain = NULL; 134 } 135 return (ret); 136 } 137 138 /* Given name and optional domain, look up SID, type, and canonical name */ 139 idmap_retcode 140 lookup_lsa_by_name( 141 const char *name, 142 const char *domain, 143 char **ret_sidprefix, 144 uint32_t *ret_rid, 145 char **ret_name, 146 char **ret_domain, 147 idmap_id_type *ret_type) 148 { 149 lsa_account_t acct; 150 char *namedom = NULL; 151 idmap_retcode ret; 152 int rc; 153 154 (void) memset(&acct, 0, sizeof (acct)); 155 *ret_sidprefix = NULL; 156 if (ret_name != NULL) 157 *ret_name = NULL; 158 if (ret_domain != NULL) 159 *ret_domain = NULL; 160 161 if (domain != NULL) 162 (void) asprintf(&namedom, "%s@%s", name, domain); 163 else 164 namedom = strdup(name); 165 if (namedom == NULL) { 166 ret = IDMAP_ERR_MEMORY; 167 goto out; 168 } 169 170 rc = smb_lookup_lname(namedom, SidTypeUnknown, &acct); 171 if (rc != 0) { 172 idmapdlog(LOG_ERR, "Error: SMB lookup name failed."); 173 idmapdlog(LOG_ERR, 174 "Check SMB service (svc:/network/smb/server)."); 175 idmapdlog(LOG_ERR, 176 "Check connectivity to Active Directory."); 177 ret = IDMAP_ERR_OTHER; 178 goto out; 179 } 180 if (acct.a_status == NT_STATUS_NONE_MAPPED) { 181 ret = IDMAP_ERR_NOTFOUND; 182 goto out; 183 } 184 if (acct.a_status != NT_STATUS_SUCCESS) { 185 idmapdlog(LOG_WARNING, 186 "Warning: SMB lookup name(%s) failed (0x%x)", 187 namedom, acct.a_status); 188 /* Fail soft */ 189 ret = IDMAP_ERR_NOTFOUND; 190 goto out; 191 } 192 193 rc = smb_sid_splitstr(acct.a_sid, ret_rid); 194 assert(rc == 0); 195 *ret_sidprefix = strdup(acct.a_sid); 196 if (*ret_sidprefix == NULL) { 197 ret = IDMAP_ERR_MEMORY; 198 goto out; 199 } 200 201 ret = idmap_lsa_xlate_sid_type(&acct, ret_type); 202 if (ret != IDMAP_SUCCESS) 203 goto out; 204 205 if (ret_name != NULL) { 206 *ret_name = strdup(acct.a_name); 207 if (*ret_name == NULL) { 208 ret = IDMAP_ERR_MEMORY; 209 goto out; 210 } 211 } 212 213 if (ret_domain != NULL) { 214 *ret_domain = strdup(acct.a_domain); 215 if (*ret_domain == NULL) { 216 ret = IDMAP_ERR_MEMORY; 217 goto out; 218 } 219 } 220 221 ret = IDMAP_SUCCESS; 222 223 out: 224 free(namedom); 225 if (ret != IDMAP_SUCCESS) { 226 if (ret_name != NULL) { 227 free(*ret_name); 228 *ret_name = NULL; 229 } 230 if (ret_domain != NULL) { 231 free(*ret_domain); 232 *ret_domain = NULL; 233 } 234 free(*ret_sidprefix); 235 *ret_sidprefix = NULL; 236 } 237 return (ret); 238 } 239 240 /* 241 * This exists just so we can avoid exposing all of idmapd to libsmb.h. 242 * Like the above functions, it's a door call over to smbd. 243 */ 244 void 245 notify_dc_changed(void) 246 { 247 smb_notify_dc_changed(); 248 } 249