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 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <stdlib.h> 27 #include <string.h> 28 #include <synch.h> 29 30 #include <smbsrv/libsmb.h> 31 32 static int wk_init = 0; 33 static rwlock_t wk_rwlock; 34 35 static char *wka_nbdomain[] = { 36 "", 37 "NT Pseudo Domain", 38 "NT Authority", 39 "Builtin", 40 "Internet$" 41 }; 42 43 /* 44 * Predefined well known accounts table 45 */ 46 static smb_wka_t wka_tbl[] = { 47 { 0, "S-1-0-0", "Null", 48 SidTypeWellKnownGroup, 0, NULL, NULL }, 49 { 0, "S-1-1-0", "Everyone", 50 SidTypeWellKnownGroup, 0, NULL, NULL }, 51 { 0, "S-1-2-0", "Local", 52 SidTypeWellKnownGroup, 0, NULL, NULL }, 53 { 0, "S-1-3-0", "Creator Owner", 54 SidTypeWellKnownGroup, 0, NULL, NULL }, 55 { 0, "S-1-3-1", "Creator Group", 56 SidTypeWellKnownGroup, 0, NULL, NULL }, 57 { 0, "S-1-3-2", "Creator Owner Server", 58 SidTypeWellKnownGroup, 0, NULL, NULL }, 59 { 0, "S-1-3-3", "Creator Group Server", 60 SidTypeWellKnownGroup, 0, NULL, NULL }, 61 { 0, "S-1-3-4", "Owner Rights", 62 SidTypeWellKnownGroup, 0, NULL, NULL }, 63 { 0, "S-1-3-5", "Group Rights", 64 SidTypeWellKnownGroup, 0, NULL, NULL }, 65 { 1, "S-1-5", "NT Pseudo Domain", 66 SidTypeDomain, 0, NULL, NULL }, 67 { 2, "S-1-5-1", "Dialup", 68 SidTypeWellKnownGroup, 0, NULL, NULL }, 69 { 2, "S-1-5-2", "Network", 70 SidTypeWellKnownGroup, 0, NULL, NULL }, 71 { 2, "S-1-5-3", "Batch", 72 SidTypeWellKnownGroup, 0, NULL, NULL }, 73 { 2, "S-1-5-4", "Interactive", 74 SidTypeWellKnownGroup, 0, NULL, NULL }, 75 { 2, "S-1-5-6", "Service", 76 SidTypeWellKnownGroup, 0, NULL, NULL }, 77 { 2, "S-1-5-7", "Anonymous", 78 SidTypeWellKnownGroup, 0, NULL, NULL }, 79 { 2, "S-1-5-8", "Proxy", 80 SidTypeWellKnownGroup, 0, NULL, NULL }, 81 { 2, "S-1-5-9", "Enterprise Domain Controllers", 82 SidTypeWellKnownGroup, 0, NULL, NULL }, 83 { 2, "S-1-5-10", "Self", 84 SidTypeWellKnownGroup, 0, NULL, NULL }, 85 { 2, "S-1-5-11", "Authenticated Users", 86 SidTypeWellKnownGroup, 0, NULL, NULL }, 87 { 2, "S-1-5-12", "Restricted", 88 SidTypeWellKnownGroup, 0, NULL, NULL }, 89 { 2, "S-1-5-13", "Terminal Server User", 90 SidTypeWellKnownGroup, 0, NULL, NULL }, 91 { 2, "S-1-5-14", "Remote Interactive Logon", 92 SidTypeWellKnownGroup, 0, NULL, NULL }, 93 { 2, "S-1-5-15", "This Organization", 94 SidTypeWellKnownGroup, 0, NULL, NULL }, 95 { 2, "S-1-5-18", "System", 96 SidTypeWellKnownGroup, 0, NULL, NULL }, 97 { 2, "S-1-5-19", "Local Service", 98 SidTypeWellKnownGroup, 0, NULL, NULL }, 99 { 2, "S-1-5-20", "Network Service", 100 SidTypeWellKnownGroup, 0, NULL, NULL }, 101 { 2, "S-1-5-33", "Write Restricted", 102 SidTypeWellKnownGroup, 0, NULL, NULL }, 103 { 2, "S-1-5-1000", "Other Organization", 104 SidTypeWellKnownGroup, 0, NULL, NULL }, 105 { 3, "S-1-5-32", "Builtin", 106 SidTypeDomain, 0, NULL, NULL }, 107 { 4, "S-1-7", "Internet$", 108 SidTypeDomain, 0, NULL, NULL }, 109 110 { 3, "S-1-5-32-544", "Administrators", SidTypeAlias, 111 SMB_WKAFLG_LGRP_ENABLE, 112 "Members can fully administer the computer/domain", NULL }, 113 { 3, "S-1-5-32-545", "Users", 114 SidTypeAlias, 0, NULL, NULL }, 115 { 3, "S-1-5-32-546", "Guests", 116 SidTypeAlias, 0, NULL, NULL }, 117 { 3, "S-1-5-32-547", "Power Users", SidTypeAlias, 118 SMB_WKAFLG_LGRP_ENABLE, "Members can share directories", NULL }, 119 { 3, "S-1-5-32-548", "Account Operators", 120 SidTypeAlias, 0, NULL, NULL }, 121 { 3, "S-1-5-32-549", "Server Operators", 122 SidTypeAlias, 0, NULL, NULL }, 123 { 3, "S-1-5-32-550", "Print Operators", 124 SidTypeAlias, 0, NULL, NULL }, 125 { 3, "S-1-5-32-551", "Backup Operators", SidTypeAlias, 126 SMB_WKAFLG_LGRP_ENABLE, 127 "Members can bypass file security to back up files", NULL }, 128 { 3, "S-1-5-32-552", "Replicator", 129 SidTypeAlias, 0, NULL, NULL }, 130 { 3, "S-1-5-32-766", "Current Owner", 131 SidTypeAlias, 0, NULL, NULL }, 132 { 3, "S-1-5-32-767", "Current Group", 133 SidTypeAlias, 0, NULL, NULL }, 134 }; 135 136 #define SMB_WKA_NUM (sizeof (wka_tbl)/sizeof (wka_tbl[0])) 137 138 /* 139 * Looks up well known accounts table for the given SID. 140 * Upon success returns a pointer to the account entry in 141 * the table, otherwise returns NULL. 142 */ 143 smb_wka_t * 144 smb_wka_lookup_sid(smb_sid_t *sid) 145 { 146 smb_wka_t *entry; 147 int i; 148 149 (void) rw_rdlock(&wk_rwlock); 150 151 for (i = 0; i < SMB_WKA_NUM; ++i) { 152 entry = &wka_tbl[i]; 153 if (smb_sid_cmp(sid, entry->wka_binsid)) { 154 (void) rw_unlock(&wk_rwlock); 155 return (entry); 156 } 157 } 158 159 (void) rw_unlock(&wk_rwlock); 160 return (NULL); 161 } 162 163 164 /* 165 * Looks up well known accounts table for the given name. 166 * Upon success returns a pointer to the binary SID of the 167 * entry, otherwise returns NULL. 168 */ 169 smb_sid_t * 170 smb_wka_get_sid(const char *name) 171 { 172 smb_wka_t *entry; 173 smb_sid_t *sid = NULL; 174 175 if ((entry = smb_wka_lookup_name(name)) != NULL) 176 sid = entry->wka_binsid; 177 178 return (sid); 179 } 180 181 /* 182 * Looks up well known accounts table for the given name. 183 * Upon success returns a pointer to the account entry in 184 * the table, otherwise returns NULL. 185 */ 186 smb_wka_t * 187 smb_wka_lookup_name(const char *name) 188 { 189 smb_wka_t *entry; 190 int i; 191 192 (void) rw_rdlock(&wk_rwlock); 193 for (i = 0; i < SMB_WKA_NUM; ++i) { 194 entry = &wka_tbl[i]; 195 if (!smb_strcasecmp(name, entry->wka_name, 0)) { 196 (void) rw_unlock(&wk_rwlock); 197 return (entry); 198 } 199 } 200 201 (void) rw_unlock(&wk_rwlock); 202 return (NULL); 203 } 204 205 /* 206 * Lookup a name in the BUILTIN domain. 207 */ 208 smb_wka_t * 209 smb_wka_lookup_builtin(const char *name) 210 { 211 smb_wka_t *entry; 212 int i; 213 214 (void) rw_rdlock(&wk_rwlock); 215 for (i = 0; i < SMB_WKA_NUM; ++i) { 216 entry = &wka_tbl[i]; 217 218 if (entry->wka_domidx != 3) 219 continue; 220 221 if (!smb_strcasecmp(name, entry->wka_name, 0)) { 222 (void) rw_unlock(&wk_rwlock); 223 return (entry); 224 } 225 } 226 227 (void) rw_unlock(&wk_rwlock); 228 return (NULL); 229 } 230 231 /* 232 * Returns the Netbios domain name for the given index 233 */ 234 char * 235 smb_wka_get_domain(int idx) 236 { 237 if ((idx >= 0) && (idx < SMB_WKA_NUM)) 238 return (wka_nbdomain[idx]); 239 240 return (NULL); 241 } 242 243 /* 244 * This function adds well known groups to groups in a user's 245 * access token (gids). 246 * 247 * "Network" SID is added for all users connecting over CIFS. 248 * 249 * "Authenticated Users" SID is added for all users except Guest 250 * and Anonymous. 251 * 252 * "Guests" SID is added for guest users and Administrators SID 253 * is added for admin users. 254 */ 255 uint32_t 256 smb_wka_token_groups(uint32_t flags, smb_ids_t *gids) 257 { 258 smb_id_t *id; 259 int total_cnt; 260 261 total_cnt = gids->i_cnt + 3; 262 263 gids->i_ids = realloc(gids->i_ids, total_cnt * sizeof (smb_id_t)); 264 if (gids->i_ids == NULL) 265 return (NT_STATUS_NO_MEMORY); 266 267 id = gids->i_ids + gids->i_cnt; 268 id->i_sid = smb_sid_dup(smb_wka_get_sid("Network")); 269 id->i_attrs = 0x7; 270 if (id->i_sid == NULL) 271 return (NT_STATUS_NO_MEMORY); 272 id++; 273 gids->i_cnt++; 274 275 if ((flags & SMB_ATF_ANON) == 0) { 276 if (flags & SMB_ATF_GUEST) 277 id->i_sid = smb_sid_dup(smb_wka_get_sid("Guests")); 278 else 279 id->i_sid = 280 smb_sid_dup(smb_wka_get_sid("Authenticated Users")); 281 id->i_attrs = 0x7; 282 if (id->i_sid == NULL) 283 return (NT_STATUS_NO_MEMORY); 284 id++; 285 gids->i_cnt++; 286 } 287 288 if (flags & SMB_ATF_ADMIN) { 289 id->i_sid = smb_sid_dup(smb_wka_get_sid("Administrators")); 290 id->i_attrs = 0x7; 291 if (id->i_sid == NULL) 292 return (NT_STATUS_NO_MEMORY); 293 gids->i_cnt++; 294 } 295 296 return (NT_STATUS_SUCCESS); 297 } 298 299 /* 300 * smb_wka_init 301 * 302 * Generate binary SIDs from the string SIDs in the table 303 * and set the proper field. 304 * 305 * Caller MUST not store the binary SID pointer anywhere that 306 * could lead to freeing it. 307 * 308 * This function should only be called once. 309 */ 310 int 311 smb_wka_init(void) 312 { 313 smb_wka_t *entry; 314 int i; 315 316 (void) rw_wrlock(&wk_rwlock); 317 if (wk_init) { 318 (void) rw_unlock(&wk_rwlock); 319 return (1); 320 } 321 322 for (i = 0; i < SMB_WKA_NUM; ++i) { 323 entry = &wka_tbl[i]; 324 entry->wka_binsid = smb_sid_fromstr(entry->wka_sid); 325 if (entry->wka_binsid == NULL) { 326 (void) rw_unlock(&wk_rwlock); 327 smb_wka_fini(); 328 return (0); 329 } 330 } 331 332 wk_init = 1; 333 (void) rw_unlock(&wk_rwlock); 334 return (1); 335 } 336 337 void 338 smb_wka_fini(void) 339 { 340 int i; 341 342 (void) rw_wrlock(&wk_rwlock); 343 if (wk_init == 0) { 344 (void) rw_unlock(&wk_rwlock); 345 return; 346 } 347 348 for (i = 0; i < SMB_WKA_NUM; ++i) { 349 if (wka_tbl[i].wka_binsid) { 350 free(wka_tbl[i].wka_binsid); 351 wka_tbl[i].wka_binsid = NULL; 352 } 353 } 354 355 wk_init = 0; 356 (void) rw_unlock(&wk_rwlock); 357 } 358