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