Print this page
SUP-549 Can't remove the Domain Admin from the local administrators group. (fix copyrights)
SUP-549 Can't remove the Domain Admin from the local administrators group.
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c
+++ new/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 - * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
24 23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
25 24 * Copyright (c) 2013 RackTop Systems.
25 + * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
26 26 */
27 27
28 28 #include <stdlib.h>
29 29 #include <strings.h>
30 30 #include <unistd.h>
31 31 #include <syslog.h>
32 32 #include <thread.h>
33 33 #include <synch.h>
34 34 #include <grp.h>
35 35 #include <assert.h>
36 36 #include <libintl.h>
37 37 #include <smbsrv/libsmb.h>
38 38 #include <smb_sqlite.h>
39 39 #include <sys/types.h>
40 40 #include <sys/stat.h>
41 41 #include <sys/param.h>
42 42 #include <libcmdutils.h>
43 43
44 44 /*
45 45 * Local domain SID (aka machine SID) is not stored in the domain table
46 46 * therefore the index is 0
47 47 */
48 48 #define SMB_LGRP_LOCAL_IDX 0
49 49 #define SMB_LGRP_BUILTIN_IDX 1
50 50
51 51 #define SMB_LGRP_DB_NAME "/var/smb/smbgroup.db"
52 52 #define SMB_LGRP_DB_TIMEOUT 3000 /* in millisecond */
53 53 #define SMB_LGRP_DB_VERMAJOR 1
54 54 #define SMB_LGRP_DB_VERMINOR 0
55 55 #define SMB_LGRP_DB_MAGIC 0x4C475250 /* LGRP */
56 56
57 57 #define SMB_LGRP_DB_ORD 1 /* open read-only */
58 58 #define SMB_LGRP_DB_ORW 2 /* open read/write */
59 59
60 60 #define SMB_LGRP_DB_ADDMEMBER 1
61 61 #define SMB_LGRP_DB_DELMEMBER 2
62 62
63 63 /*
64 64 * members column of the groups table is an array of
65 65 * member structure smb_lgmid_t defined below.
66 66 *
67 67 * privs column of the groups table is an array of bytes
68 68 * where each byte is the id of an enable privilege
69 69 */
70 70 #define SMB_LGRP_DB_SQL \
71 71 "CREATE TABLE db_info (" \
72 72 " ver_major INTEGER," \
73 73 " ver_minor INTEGER," \
74 74 " magic INTEGER" \
75 75 ");" \
76 76 "" \
77 77 "CREATE TABLE domains (" \
78 78 " dom_idx INTEGER PRIMARY KEY," \
79 79 " dom_sid TEXT UNIQUE," \
80 80 " dom_cnt INTEGER" \
81 81 ");" \
82 82 "" \
83 83 "CREATE UNIQUE INDEX domsid_idx ON domains (dom_sid);" \
84 84 "" \
85 85 "CREATE TABLE groups (" \
86 86 " name TEXT PRIMARY KEY," \
87 87 " sid_idx INTEGER," \
88 88 " sid_rid INTEGER," \
89 89 " sid_type INTEGER," \
90 90 " sid_attrs INTEGER," \
91 91 " comment TEXT," \
92 92 " n_privs INTEGER," \
93 93 " privs BLOB," \
94 94 " n_members INTEGER," \
95 95 " members BLOB" \
96 96 ");" \
97 97 "" \
98 98 "CREATE INDEX grprid_idx ON groups (sid_rid);"
99 99
100 100 /*
101 101 * Number of groups table columns
102 102 */
103 103 #define SMB_LGRP_GTBL_NCOL 10
104 104
105 105 #define SMB_LGRP_GTBL_NAME 0
106 106 #define SMB_LGRP_GTBL_SIDIDX 1
107 107 #define SMB_LGRP_GTBL_SIDRID 2
108 108 #define SMB_LGRP_GTBL_SIDTYP 3
109 109 #define SMB_LGRP_GTBL_SIDATR 4
110 110 #define SMB_LGRP_GTBL_CMNT 5
111 111 #define SMB_LGRP_GTBL_NPRIVS 6
112 112 #define SMB_LGRP_GTBL_PRIVS 7
113 113 #define SMB_LGRP_GTBL_NMEMBS 8
114 114 #define SMB_LGRP_GTBL_MEMBS 9
115 115
116 116 #define SMB_LGRP_INFO_NONE 0x00
117 117 #define SMB_LGRP_INFO_NAME 0x01
118 118 #define SMB_LGRP_INFO_CMNT 0x02
119 119 #define SMB_LGRP_INFO_SID 0x04
120 120 #define SMB_LGRP_INFO_PRIV 0x08
121 121 #define SMB_LGRP_INFO_MEMB 0x10
122 122 #define SMB_LGRP_INFO_ALL 0x1F
123 123
124 124 #define SMB_LGRP_PGRP_GRPTMP "/etc/gtmp"
125 125 #define SMB_LGRP_PGRP_GRPBUFSIZ 5120
126 126 #define SMB_LGRP_PGRP_GROUP "/etc/group"
127 127 #define SMB_LGRP_PGRP_MAXGLEN 9 /* max length of group name */
128 128 #define SMB_LGRP_PGRP_DEFRID 1000 /* lowest cifs created gid */
129 129
130 130 #define SMB_LGRP_PGRP_NOTUNIQUE 0
131 131 #define SMB_LGRP_PGRP_RESERVED 1
132 132 #define SMB_LGRP_PGRP_UNIQUE 2
133 133 #define SMB_LGRP_PGRP_TOOBIG 3
134 134 #define SMB_LGRP_PGRP_INVALID 4
|
↓ open down ↓ |
99 lines elided |
↑ open up ↑ |
135 135
136 136 #define NULL_MSGCHK(msg) ((msg) ? (msg) : "NULL")
137 137
138 138 /* Member ID */
139 139 typedef struct smb_lgmid {
140 140 uint32_t m_idx;
141 141 uint32_t m_rid;
142 142 uint16_t m_type;
143 143 } smb_lgmid_t;
144 144
145 +/* Buffer size to hold hex form of the above (>24). */
145 146 #define SMB_LGRP_MID_HEXSZ 32
146 147
148 +/* Size of idx,rid parts of above, in hex form. */
149 +#define SMB_LGRP_IDXRID_LEN 16
150 +
147 151 /* Member list */
148 152 typedef struct smb_lgmlist {
149 153 uint32_t m_cnt;
150 154 char *m_ids;
151 155 } smb_lgmlist_t;
152 156
153 157 /* Privilege ID */
154 158 typedef uint8_t smb_lgpid_t;
155 159
156 160 /* Privilege list */
157 161 typedef struct smb_lgplist {
158 162 uint32_t p_cnt;
159 163 smb_lgpid_t *p_ids;
160 164 } smb_lgplist_t;
161 165
162 166 static struct {
163 167 int errnum;
164 168 char *errmsg;
165 169 } errtab[] = {
166 170 { SMB_LGRP_SUCCESS, "success" },
167 171 { SMB_LGRP_INVALID_ARG, "invalid argument" },
168 172 { SMB_LGRP_INVALID_MEMBER, "invalid member type" },
169 173 { SMB_LGRP_INVALID_NAME, "invalid name" },
170 174 { SMB_LGRP_NOT_FOUND, "group not found" },
171 175 { SMB_LGRP_EXISTS, "group exists" },
172 176 { SMB_LGRP_NO_SID, "cannot obtain a SID" },
173 177 { SMB_LGRP_NO_LOCAL_SID, "cannot get the machine SID" },
174 178 { SMB_LGRP_SID_NOTLOCAL, "local account has non-local SID" },
175 179 { SMB_LGRP_WKSID,
176 180 "operation not permitted on well-known account" },
177 181 { SMB_LGRP_NO_MEMORY, "not enough memory" },
178 182 { SMB_LGRP_DB_ERROR, "database operation error" },
179 183 { SMB_LGRP_DBINIT_ERROR, "database initialization error" },
180 184 { SMB_LGRP_INTERNAL_ERROR, "internal error" },
181 185 { SMB_LGRP_MEMBER_IN_GROUP, "member already in group" },
182 186 { SMB_LGRP_MEMBER_NOT_IN_GROUP, "not a member" },
183 187 { SMB_LGRP_NO_SUCH_PRIV, "no such privilege" },
184 188 { SMB_LGRP_NO_SUCH_DOMAIN, "no such domain SID" },
185 189 { SMB_LGRP_PRIV_HELD, "privilege already held" },
186 190 { SMB_LGRP_PRIV_NOT_HELD, "privilege not held" },
187 191 { SMB_LGRP_BAD_DATA, "bad data" },
188 192 { SMB_LGRP_NO_MORE, "no more groups" },
189 193 { SMB_LGRP_DBOPEN_FAILED, "database open failed" },
190 194 { SMB_LGRP_DBEXEC_FAILED, "database operation failed" },
191 195 { SMB_LGRP_DBINIT_FAILED, "database initialization failed" },
192 196 { SMB_LGRP_DOMLKP_FAILED, "domain SID lookup failed" },
193 197 { SMB_LGRP_DOMINS_FAILED, "domain SID insert failed" },
194 198 { SMB_LGRP_INSERT_FAILED, "group insert failed" },
195 199 { SMB_LGRP_DELETE_FAILED, "group delete failed" },
196 200 { SMB_LGRP_UPDATE_FAILED, "group update failed" },
197 201 { SMB_LGRP_LOOKUP_FAILED, "group lookup failed" },
198 202 { SMB_LGRP_OFFLINE, "local group service is offline" },
199 203 { SMB_LGRP_POSIXCREATE_FAILED, "posix group create failed" }
200 204 };
201 205
202 206 /*
203 207 * Serialization for the local group API.
204 208 */
205 209 typedef struct {
206 210 mutex_t lg_mutex;
207 211 cond_t lg_cv;
208 212 boolean_t lg_online;
209 213 uint32_t lg_refcnt;
210 214 smb_sid_t *lg_machine_sid;
211 215 } smb_localgrp_t;
212 216
213 217 static smb_localgrp_t smb_localgrp;
214 218
215 219 static boolean_t smb_lgrp_enter(void);
216 220 static void smb_lgrp_exit(void);
217 221 static int smb_lgrp_db_init(void);
218 222 static sqlite *smb_lgrp_db_open(int);
219 223 static void smb_lgrp_db_close(sqlite *);
220 224 static int smb_lgrp_db_setinfo(sqlite *);
221 225
222 226 static boolean_t smb_lgrp_gtbl_exists(sqlite *, char *);
223 227 static int smb_lgrp_gtbl_lookup(sqlite *, int, smb_group_t *, int, ...);
224 228 static int smb_lgrp_gtbl_insert(sqlite *, smb_group_t *);
225 229 static int smb_lgrp_gtbl_update(sqlite *, char *, smb_group_t *, int);
226 230 static int smb_lgrp_gtbl_delete(sqlite *, char *);
227 231 static int smb_lgrp_gtbl_update_mlist(sqlite *, char *, smb_gsid_t *, int);
228 232 static int smb_lgrp_gtbl_update_plist(sqlite *, char *, uint8_t, boolean_t);
229 233 static int smb_lgrp_gtbl_count(sqlite *, int, int *);
230 234
231 235 static int smb_lgrp_dtbl_insert(sqlite *, char *, uint32_t *);
232 236 static int smb_lgrp_dtbl_getidx(sqlite *, smb_sid_t *, uint16_t,
233 237 uint32_t *, uint32_t *);
234 238 static int smb_lgrp_dtbl_getsid(sqlite *, uint32_t, smb_sid_t **);
235 239
236 240 static int smb_lgrp_mlist_add(smb_lgmlist_t *, smb_lgmid_t *, smb_lgmlist_t *);
237 241 static int smb_lgrp_mlist_del(smb_lgmlist_t *, smb_lgmid_t *, smb_lgmlist_t *);
238 242
239 243 static int smb_lgrp_plist_add(smb_lgplist_t *, smb_lgpid_t, smb_lgplist_t *);
240 244 static int smb_lgrp_plist_del(smb_lgplist_t *, smb_lgpid_t, smb_lgplist_t *);
241 245
242 246 static void smb_lgrp_encode_privset(smb_group_t *, smb_lgplist_t *);
243 247
244 248 static int smb_lgrp_decode(smb_group_t *, char **, int, sqlite *);
245 249 static int smb_lgrp_decode_privset(smb_group_t *, char *, char *);
246 250 static int smb_lgrp_decode_members(smb_group_t *, char *, char *, sqlite *);
247 251
248 252 static void smb_lgrp_set_default_privs(smb_group_t *);
249 253 static boolean_t smb_lgrp_normalize_name(char *);
250 254 static boolean_t smb_lgrp_chkmember(uint16_t);
251 255 static int smb_lgrp_getsid(int, uint32_t *, uint16_t, sqlite *, smb_sid_t **);
252 256 static int smb_lgrp_getgid(uint32_t rid, gid_t *gid);
253 257 static boolean_t smb_lgrp_exists(char *);
254 258 static int smb_lgrp_pgrp_add(char *);
255 259
256 260 /*
257 261 * smb_lgrp_add
258 262 *
259 263 * Create a local group with the given name and comment.
260 264 * This new group doesn't have any members and no enabled
261 265 * privileges.
262 266 *
263 267 * No well-known accounts can be added other than Administators,
264 268 * Backup Operators and Power Users. These built-in groups
265 269 * won't have any members when created but a set of default
266 270 * privileges will be enabled for them.
267 271 */
268 272 int
269 273 smb_lgrp_add(char *gname, char *cmnt)
270 274 {
271 275 smb_wka_t *wka;
272 276 struct group *pxgrp;
273 277 smb_group_t grp;
274 278 smb_sid_t *sid = NULL;
275 279 sqlite *db;
276 280 int rc;
277 281
278 282 if (!smb_lgrp_normalize_name(gname))
279 283 return (SMB_LGRP_INVALID_NAME);
280 284
281 285 if (cmnt && (strlen(cmnt) > SMB_LGRP_COMMENT_MAX))
282 286 return (SMB_LGRP_INVALID_ARG);
283 287
284 288 bzero(&grp, sizeof (grp));
285 289 grp.sg_name = smb_strlwr(gname);
286 290 grp.sg_cmnt = cmnt;
287 291
288 292 if (!smb_lgrp_enter())
289 293 return (SMB_LGRP_OFFLINE);
290 294
291 295 wka = smb_wka_lookup_name(gname);
292 296 if (wka == NULL) {
293 297 if ((pxgrp = getgrnam(gname)) == NULL) {
294 298 if (smb_lgrp_pgrp_add(gname) != 0) {
295 299 smb_lgrp_exit();
296 300 return (SMB_LGRP_POSIXCREATE_FAILED);
297 301 }
298 302
299 303 if ((pxgrp = getgrnam(gname)) == NULL) {
300 304 smb_lgrp_exit();
301 305 return (SMB_LGRP_NOT_FOUND);
302 306 }
303 307 }
304 308
305 309 /*
306 310 * Make sure a local SID can be obtained
307 311 */
308 312 if (smb_idmap_getsid(pxgrp->gr_gid, SMB_IDMAP_GROUP, &sid)
309 313 != IDMAP_SUCCESS) {
310 314 smb_lgrp_exit();
311 315 return (SMB_LGRP_NO_SID);
312 316 }
313 317
314 318 if (!smb_sid_indomain(smb_localgrp.lg_machine_sid, sid)) {
315 319 free(sid);
316 320 smb_lgrp_exit();
317 321 return (SMB_LGRP_SID_NOTLOCAL);
318 322 }
319 323
320 324 free(sid);
321 325 grp.sg_id.gs_type = SidTypeAlias;
322 326 grp.sg_domain = SMB_DOMAIN_LOCAL;
323 327 grp.sg_rid = pxgrp->gr_gid;
324 328 } else {
325 329 if ((wka->wka_flags & SMB_WKAFLG_LGRP_ENABLE) == 0) {
326 330 /* cannot add well-known accounts */
327 331 smb_lgrp_exit();
328 332 return (SMB_LGRP_WKSID);
329 333 }
330 334
331 335 grp.sg_id.gs_type = wka->wka_type;
332 336 if ((sid = smb_sid_fromstr(wka->wka_sid)) == NULL) {
333 337 smb_lgrp_exit();
334 338 return (SMB_LGRP_NO_MEMORY);
335 339 }
336 340
337 341 (void) smb_sid_getrid(sid, &grp.sg_rid);
338 342 free(sid);
339 343 grp.sg_domain = SMB_DOMAIN_BUILTIN;
340 344 grp.sg_privs = smb_privset_new();
341 345 smb_lgrp_set_default_privs(&grp);
342 346 }
343 347
344 348 if (smb_lgrp_exists(grp.sg_name)) {
345 349 smb_lgrp_exit();
346 350 return (SMB_LGRP_EXISTS);
347 351 }
348 352
349 353 grp.sg_attr = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT |
350 354 SE_GROUP_ENABLED;
351 355
352 356 db = smb_lgrp_db_open(SMB_LGRP_DB_ORW);
353 357 rc = smb_lgrp_gtbl_insert(db, &grp);
354 358 smb_lgrp_db_close(db);
355 359
356 360 smb_privset_free(grp.sg_privs);
357 361 smb_lgrp_exit();
358 362 return (rc);
359 363 }
360 364
361 365 /*
362 366 * smb_lgrp_rename
363 367 *
364 368 * Renames the given group
365 369 */
366 370 int
367 371 smb_lgrp_rename(char *gname, char *new_gname)
368 372 {
369 373 smb_group_t grp;
370 374 sqlite *db;
371 375 int rc;
372 376
373 377 if (!smb_lgrp_normalize_name(gname))
374 378 return (SMB_LGRP_INVALID_NAME);
375 379
376 380 if (!smb_lgrp_normalize_name(gname))
377 381 return (SMB_LGRP_INVALID_NAME);
378 382
379 383 if (smb_strcasecmp(gname, new_gname, 0) == 0)
380 384 return (SMB_LGRP_SUCCESS);
381 385
382 386 /* Cannot rename well-known groups */
383 387 if (smb_wka_lookup_name(gname) != NULL)
384 388 return (SMB_LGRP_WKSID);
385 389
386 390 /* Cannot rename to a well-known groups */
387 391 if (smb_wka_lookup_name(new_gname) != NULL)
388 392 return (SMB_LGRP_WKSID);
389 393
390 394 grp.sg_name = new_gname;
391 395
392 396 if (!smb_lgrp_enter())
393 397 return (SMB_LGRP_OFFLINE);
394 398
395 399 if (getgrnam(new_gname) == NULL) {
396 400 if (smb_lgrp_pgrp_add(new_gname) != 0) {
397 401 smb_lgrp_exit();
398 402 return (SMB_LGRP_POSIXCREATE_FAILED);
399 403 }
400 404
401 405 if (getgrnam(new_gname) == NULL) {
402 406 smb_lgrp_exit();
403 407 return (SMB_LGRP_NOT_FOUND);
404 408 }
405 409 }
406 410
407 411 db = smb_lgrp_db_open(SMB_LGRP_DB_ORW);
408 412 rc = smb_lgrp_gtbl_update(db, gname, &grp, SMB_LGRP_GTBL_NAME);
409 413 smb_lgrp_db_close(db);
410 414
411 415 smb_lgrp_exit();
412 416 return (rc);
413 417 }
414 418
415 419 /*
416 420 * smb_lgrp_delete
417 421 *
418 422 * Deletes the specified local group.
419 423 */
420 424 int
421 425 smb_lgrp_delete(char *gname)
422 426 {
423 427 sqlite *db;
424 428 int rc;
425 429
426 430 if (!smb_lgrp_normalize_name(gname))
427 431 return (SMB_LGRP_INVALID_NAME);
428 432
429 433 /* Cannot remove a built-in group */
430 434 if (smb_wka_lookup_name(gname) != NULL)
431 435 return (SMB_LGRP_WKSID);
432 436
433 437
434 438 if (!smb_lgrp_exists(gname))
435 439 return (SMB_LGRP_NOT_FOUND);
436 440
437 441 if (!smb_lgrp_enter())
438 442 return (SMB_LGRP_OFFLINE);
439 443
440 444 db = smb_lgrp_db_open(SMB_LGRP_DB_ORW);
441 445 rc = smb_lgrp_gtbl_delete(db, gname);
442 446 smb_lgrp_db_close(db);
443 447
444 448 smb_lgrp_exit();
445 449 return (rc);
446 450 }
447 451
448 452 /*
449 453 * smb_lgrp_setcmnt
450 454 *
451 455 * Sets the description for the given group
452 456 */
453 457 int
454 458 smb_lgrp_setcmnt(char *gname, char *cmnt)
455 459 {
456 460 smb_group_t grp;
457 461 sqlite *db;
458 462 int rc;
459 463
460 464 if (!smb_lgrp_normalize_name(gname))
461 465 return (SMB_LGRP_INVALID_NAME);
462 466
463 467 if (cmnt && (strlen(cmnt) > SMB_LGRP_COMMENT_MAX))
464 468 return (SMB_LGRP_INVALID_ARG);
465 469
466 470 grp.sg_cmnt = cmnt;
467 471
468 472 if (!smb_lgrp_enter())
469 473 return (SMB_LGRP_OFFLINE);
470 474
471 475 db = smb_lgrp_db_open(SMB_LGRP_DB_ORW);
472 476 rc = smb_lgrp_gtbl_update(db, gname, &grp, SMB_LGRP_GTBL_CMNT);
473 477 smb_lgrp_db_close(db);
474 478
475 479 smb_lgrp_exit();
476 480 return (rc);
477 481 }
478 482
479 483 /*
480 484 * smb_lgrp_getcmnt
481 485 *
482 486 * Obtain the description of the specified group
483 487 */
484 488 int
485 489 smb_lgrp_getcmnt(char *gname, char **cmnt)
486 490 {
487 491 smb_group_t grp;
488 492 sqlite *db;
489 493 int rc;
490 494
491 495 if (!smb_lgrp_normalize_name(gname))
492 496 return (SMB_LGRP_INVALID_NAME);
493 497
494 498 if (cmnt == NULL)
495 499 return (SMB_LGRP_INVALID_ARG);
496 500
497 501 if (!smb_lgrp_enter())
498 502 return (SMB_LGRP_OFFLINE);
499 503
500 504 db = smb_lgrp_db_open(SMB_LGRP_DB_ORD);
501 505 rc = smb_lgrp_gtbl_lookup(db, SMB_LGRP_GTBL_NAME, &grp,
502 506 SMB_LGRP_INFO_CMNT, gname);
503 507 smb_lgrp_db_close(db);
504 508 smb_lgrp_exit();
505 509
506 510 if (rc == SMB_LGRP_SUCCESS) {
507 511 *cmnt = grp.sg_cmnt;
508 512 grp.sg_cmnt = NULL;
509 513 smb_lgrp_free(&grp);
510 514 }
511 515
512 516 return (rc);
513 517 }
514 518
515 519
516 520 /*
517 521 * smb_lgrp_setpriv
518 522 *
519 523 * Enable/disable the specified privilge for the group
520 524 */
521 525 int
522 526 smb_lgrp_setpriv(char *gname, uint8_t priv_lid, boolean_t enable)
523 527 {
524 528 sqlite *db;
525 529 int rc;
526 530
527 531 if (!smb_lgrp_normalize_name(gname))
528 532 return (SMB_LGRP_INVALID_NAME);
529 533
530 534 if ((priv_lid < SE_MIN_LUID) || (priv_lid > SE_MAX_LUID))
531 535 return (SMB_LGRP_NO_SUCH_PRIV);
532 536
533 537 if (!smb_lgrp_enter())
534 538 return (SMB_LGRP_OFFLINE);
535 539
536 540 db = smb_lgrp_db_open(SMB_LGRP_DB_ORW);
537 541 rc = smb_lgrp_gtbl_update_plist(db, gname, priv_lid, enable);
538 542 smb_lgrp_db_close(db);
539 543 smb_lgrp_exit();
540 544
541 545 if (enable) {
542 546 if (rc == SMB_LGRP_PRIV_HELD)
543 547 rc = SMB_LGRP_SUCCESS;
544 548 } else {
545 549 if (rc == SMB_LGRP_PRIV_NOT_HELD)
546 550 rc = SMB_LGRP_SUCCESS;
547 551 }
548 552
549 553 return (rc);
550 554 }
551 555
552 556 /*
553 557 * smb_lgrp_getpriv
554 558 *
555 559 * Obtain the status of the specified privilge for the group
556 560 */
557 561 int
558 562 smb_lgrp_getpriv(char *gname, uint8_t priv_lid, boolean_t *enable)
559 563 {
560 564 sqlite *db;
561 565 smb_group_t grp;
562 566 int rc;
563 567
564 568 if (!smb_lgrp_normalize_name(gname))
565 569 return (SMB_LGRP_INVALID_NAME);
566 570
567 571 if ((priv_lid < SE_MIN_LUID) || (priv_lid > SE_MAX_LUID))
568 572 return (SMB_LGRP_NO_SUCH_PRIV);
569 573
570 574 if (!smb_lgrp_enter())
571 575 return (SMB_LGRP_OFFLINE);
572 576
573 577 db = smb_lgrp_db_open(SMB_LGRP_DB_ORD);
574 578 rc = smb_lgrp_gtbl_lookup(db, SMB_LGRP_GTBL_NAME, &grp,
575 579 SMB_LGRP_INFO_PRIV, gname);
576 580 smb_lgrp_db_close(db);
577 581 smb_lgrp_exit();
578 582
579 583 if (rc == SMB_LGRP_SUCCESS) {
580 584 *enable = (smb_privset_query(grp.sg_privs, priv_lid) == 1);
581 585 smb_lgrp_free(&grp);
582 586 }
583 587
584 588 return (rc);
585 589 }
586 590
587 591 /*
588 592 * smb_lgrp_add_member
589 593 *
590 594 * Add the given account to the specified group as its member.
591 595 */
592 596 int
593 597 smb_lgrp_add_member(char *gname, smb_sid_t *msid, uint16_t sid_type)
594 598 {
595 599 sqlite *db;
596 600 smb_gsid_t mid;
597 601 int rc;
598 602
599 603 if (!smb_lgrp_normalize_name(gname))
600 604 return (SMB_LGRP_INVALID_NAME);
601 605
602 606 if (!smb_sid_isvalid(msid))
603 607 return (SMB_LGRP_INVALID_ARG);
604 608
605 609 if (!smb_lgrp_chkmember(sid_type))
606 610 return (SMB_LGRP_INVALID_MEMBER);
607 611
608 612 mid.gs_sid = msid;
609 613 mid.gs_type = sid_type;
610 614
611 615 if (!smb_lgrp_enter())
612 616 return (SMB_LGRP_OFFLINE);
613 617
614 618 db = smb_lgrp_db_open(SMB_LGRP_DB_ORW);
615 619 rc = smb_lgrp_gtbl_update_mlist(db, gname, &mid, SMB_LGRP_DB_ADDMEMBER);
616 620 smb_lgrp_db_close(db);
617 621
618 622 smb_lgrp_exit();
619 623 return (rc);
620 624 }
621 625
622 626 /*
623 627 * smb_lgrp_del_member
624 628 *
625 629 * Delete the specified member from the given group.
626 630 */
627 631 int
628 632 smb_lgrp_del_member(char *gname, smb_sid_t *msid, uint16_t sid_type)
629 633 {
630 634 sqlite *db;
631 635 smb_gsid_t mid;
632 636 int rc;
633 637
634 638 if (!smb_lgrp_normalize_name(gname))
635 639 return (SMB_LGRP_INVALID_NAME);
636 640
637 641 if (!smb_sid_isvalid(msid))
638 642 return (SMB_LGRP_INVALID_ARG);
639 643
640 644 mid.gs_sid = msid;
641 645 mid.gs_type = sid_type;
642 646
643 647 if (!smb_lgrp_enter())
644 648 return (SMB_LGRP_OFFLINE);
645 649
646 650 db = smb_lgrp_db_open(SMB_LGRP_DB_ORW);
647 651 rc = smb_lgrp_gtbl_update_mlist(db, gname, &mid, SMB_LGRP_DB_DELMEMBER);
648 652 smb_lgrp_db_close(db);
649 653
650 654 smb_lgrp_exit();
651 655 return (rc);
652 656 }
653 657
654 658 /*
655 659 * smb_lgrp_getbyname
656 660 *
657 661 * Retrieves the information of the group specified by
658 662 * the given name.
659 663 *
660 664 * Note that this function doesn't allocate the group
661 665 * structure itself only the fields, so the given grp
662 666 * pointer has to point to a group structure.
663 667 * Caller must free the allocated memories for the fields
664 668 * by calling smb_lgrp_free().
665 669 */
666 670 int
667 671 smb_lgrp_getbyname(char *gname, smb_group_t *grp)
668 672 {
669 673 sqlite *db;
670 674 int rc;
671 675
672 676 if (!smb_lgrp_normalize_name(gname))
673 677 return (SMB_LGRP_INVALID_NAME);
674 678
675 679 if (!smb_lgrp_enter())
676 680 return (SMB_LGRP_OFFLINE);
677 681
678 682 db = smb_lgrp_db_open(SMB_LGRP_DB_ORD);
679 683 rc = smb_lgrp_gtbl_lookup(db, SMB_LGRP_GTBL_NAME, grp,
680 684 SMB_LGRP_INFO_ALL, gname);
681 685 smb_lgrp_db_close(db);
682 686
683 687 smb_lgrp_exit();
684 688 return (rc);
685 689 }
686 690
687 691 /*
688 692 * smb_lgrp_getbyrid
689 693 *
690 694 * Retrieves the information of the group specified by
691 695 * the given RID and domain type.
692 696 *
693 697 * Note that this function doesn't allocate the group
694 698 * structure itself only the fields, so the given grp
695 699 * pointer has to point to a group structure.
696 700 * Caller must free the allocated memories for the fields
697 701 * by calling smb_lgrp_free().
698 702 *
699 703 * If grp is NULL no information would be returned. The
700 704 * return value of SMB_LGRP_SUCCESS will indicate that a
701 705 * group with the given information exists.
702 706 */
703 707 int
704 708 smb_lgrp_getbyrid(uint32_t rid, smb_domain_type_t domtype, smb_group_t *grp)
705 709 {
706 710 smb_group_t tmpgrp;
707 711 sqlite *db;
708 712 int infolvl = SMB_LGRP_INFO_ALL;
709 713 int rc;
710 714
711 715 if (!smb_lgrp_enter())
712 716 return (SMB_LGRP_OFFLINE);
713 717
714 718 if (grp == NULL) {
715 719 grp = &tmpgrp;
716 720 infolvl = SMB_LGRP_INFO_NONE;
717 721 }
718 722
719 723 db = smb_lgrp_db_open(SMB_LGRP_DB_ORD);
720 724 rc = smb_lgrp_gtbl_lookup(db, SMB_LGRP_GTBL_SIDRID, grp, infolvl,
721 725 rid, domtype);
722 726 smb_lgrp_db_close(db);
723 727
724 728 smb_lgrp_exit();
725 729 return (rc);
726 730 }
727 731
728 732 /*
729 733 * smb_lgrp_numbydomain
730 734 *
731 735 * Returns the number of groups in the given domain in the
732 736 * arg 'count'
733 737 */
734 738 int
735 739 smb_lgrp_numbydomain(smb_domain_type_t dom_type, int *count)
736 740 {
737 741 sqlite *db;
738 742 int dom_idx;
739 743 int rc;
740 744
741 745 switch (dom_type) {
742 746 case SMB_DOMAIN_LOCAL:
743 747 dom_idx = SMB_LGRP_LOCAL_IDX;
744 748 break;
745 749 case SMB_DOMAIN_BUILTIN:
746 750 dom_idx = SMB_LGRP_BUILTIN_IDX;
747 751 break;
748 752 default:
749 753 *count = 0;
750 754 return (SMB_LGRP_INVALID_ARG);
751 755 }
752 756
753 757 if (!smb_lgrp_enter())
754 758 return (SMB_LGRP_OFFLINE);
755 759
756 760 db = smb_lgrp_db_open(SMB_LGRP_DB_ORD);
757 761 rc = smb_lgrp_gtbl_count(db, dom_idx, count);
758 762 smb_lgrp_db_close(db);
759 763
760 764 smb_lgrp_exit();
761 765 return (rc);
762 766 }
763 767
764 768 /*
765 769 * smb_lgrp_free
766 770 *
767 771 * Frees the allocated memory for the fields of the given
768 772 * group structure. Note that this function doesn't free
769 773 * the group itself.
770 774 */
771 775 void
772 776 smb_lgrp_free(smb_group_t *grp)
773 777 {
774 778 int i;
775 779
776 780 if (grp == NULL)
777 781 return;
778 782
779 783 free(grp->sg_name);
780 784 free(grp->sg_cmnt);
781 785 smb_sid_free(grp->sg_id.gs_sid);
782 786 smb_privset_free(grp->sg_privs);
783 787
784 788 for (i = 0; i < grp->sg_nmembers; i++)
785 789 smb_sid_free(grp->sg_members[i].gs_sid);
786 790 free(grp->sg_members);
787 791 }
788 792
789 793 /*
790 794 * smb_lgrp_iteropen
791 795 *
792 796 * Initializes the given group iterator by opening
793 797 * the group database and creating a virtual machine
794 798 * for iteration.
795 799 */
796 800 int
797 801 smb_lgrp_iteropen(smb_giter_t *iter)
798 802 {
799 803 char *sql;
800 804 char *errmsg = NULL;
801 805 int rc = SMB_LGRP_SUCCESS;
802 806
803 807 assert(iter);
804 808
805 809 if (!smb_lgrp_enter())
806 810 return (SMB_LGRP_OFFLINE);
807 811
808 812 bzero(iter, sizeof (smb_giter_t));
809 813
810 814 sql = sqlite_mprintf("SELECT * FROM groups");
811 815 if (sql == NULL) {
812 816 smb_lgrp_exit();
813 817 return (SMB_LGRP_NO_MEMORY);
814 818 }
815 819
816 820 iter->sgi_db = smb_lgrp_db_open(SMB_LGRP_DB_ORD);
817 821 if (iter->sgi_db == NULL) {
818 822 sqlite_freemem(sql);
819 823 smb_lgrp_exit();
820 824 return (SMB_LGRP_DBOPEN_FAILED);
821 825 }
822 826
823 827 rc = sqlite_compile(iter->sgi_db, sql, NULL, &iter->sgi_vm, &errmsg);
824 828 sqlite_freemem(sql);
825 829
826 830 if (rc != SQLITE_OK) {
827 831 syslog(LOG_DEBUG, "failed to create a VM (%s)",
828 832 NULL_MSGCHK(errmsg));
829 833 rc = SMB_LGRP_DB_ERROR;
830 834 }
831 835
832 836 smb_lgrp_exit();
833 837 return (rc);
834 838 }
835 839
836 840 /*
837 841 * smb_lgrp_iterclose
838 842 *
839 843 * Closes the given group iterator.
840 844 */
841 845 void
842 846 smb_lgrp_iterclose(smb_giter_t *iter)
843 847 {
844 848 char *errmsg = NULL;
845 849 int rc;
846 850
847 851 assert(iter);
848 852
849 853 if (!smb_lgrp_enter())
850 854 return;
851 855
852 856 rc = sqlite_finalize(iter->sgi_vm, &errmsg);
853 857 if (rc != SQLITE_OK) {
854 858 syslog(LOG_DEBUG, "failed to destroy a VM (%s)",
855 859 NULL_MSGCHK(errmsg));
856 860 }
857 861
858 862 smb_lgrp_db_close(iter->sgi_db);
859 863 smb_lgrp_exit();
860 864 }
861 865
862 866 /*
863 867 * Returns B_TRUE if there has been an error during
864 868 * iteration.
865 869 */
866 870 boolean_t
867 871 smb_lgrp_itererror(smb_giter_t *iter)
868 872 {
869 873 return (iter->sgi_nerr != 0);
870 874 }
871 875
872 876 /*
873 877 * smb_lgrp_iterate
874 878 *
875 879 * Iterate through group database
876 880 * Group information is returned in provided group structure.
877 881 *
878 882 * Note that this function doesn't allocate the group
879 883 * structure itself only the fields, so the given grp
880 884 * pointer has to point to a group structure.
881 885 * Caller must free the allocated memories for the fields
882 886 * by calling smb_lgrp_free().
883 887 */
884 888 int
885 889 smb_lgrp_iterate(smb_giter_t *iter, smb_group_t *grp)
886 890 {
887 891 const char **values;
888 892 int ncol;
889 893 int rc;
890 894 int i;
891 895
892 896 if (iter->sgi_vm == NULL || iter->sgi_db == NULL)
893 897 return (SMB_LGRP_INVALID_ARG);
894 898
895 899 if (!smb_lgrp_enter())
896 900 return (SMB_LGRP_OFFLINE);
897 901
898 902 for (;;) {
899 903 bzero(grp, sizeof (smb_group_t));
900 904 rc = sqlite_step(iter->sgi_vm, &ncol, &values, NULL);
901 905 if (rc == SQLITE_DONE) {
902 906 smb_lgrp_exit();
903 907 return (SMB_LGRP_NO_MORE);
904 908 }
905 909
906 910 if (rc != SQLITE_ROW) {
907 911 smb_lgrp_exit();
908 912 return (SMB_LGRP_DBEXEC_FAILED);
909 913 }
910 914
911 915 if (ncol != SMB_LGRP_GTBL_NCOL) {
912 916 smb_lgrp_exit();
913 917 return (SMB_LGRP_DB_ERROR);
914 918 }
915 919
916 920 for (i = 0; i < ncol; i++) {
917 921 if (values[i] == NULL) {
918 922 smb_lgrp_exit();
919 923 return (SMB_LGRP_DB_ERROR);
920 924 }
921 925 }
922 926
923 927 rc = smb_lgrp_decode(grp, (char **)values, SMB_LGRP_INFO_ALL,
924 928 iter->sgi_db);
925 929 if (rc == SMB_LGRP_SUCCESS)
926 930 break;
927 931
928 932 iter->sgi_nerr++;
929 933 syslog(LOG_ERR, "smb_lgrp_iterate: %s", smb_lgrp_strerror(rc));
930 934 }
931 935
932 936 smb_lgrp_exit();
933 937 return (rc);
934 938
935 939 }
936 940
937 941 /*
938 942 * smb_lgrp_is_member
939 943 *
940 944 * Check to see if the specified account is a member of
941 945 * the given group.
942 946 */
943 947 boolean_t
944 948 smb_lgrp_is_member(smb_group_t *grp, smb_sid_t *sid)
945 949 {
946 950 int i;
947 951
948 952 if (grp == NULL || grp->sg_members == NULL || sid == NULL)
949 953 return (B_FALSE);
950 954
951 955 for (i = 0; i < grp->sg_nmembers; i++) {
952 956 if (smb_sid_cmp(grp->sg_members[i].gs_sid, sid))
953 957 return (B_TRUE);
954 958 }
955 959
956 960 return (B_FALSE);
957 961 }
958 962
959 963 /*
960 964 * smb_lgrp_strerror
961 965 *
962 966 * Returns a text for the given group error code.
963 967 */
964 968 char *
965 969 smb_lgrp_strerror(int errnum)
966 970 {
967 971 int i;
968 972 int nerr = (sizeof (errtab) / sizeof (errtab[0]));
969 973
970 974 for (i = 0; i < nerr; ++i) {
971 975 if (errnum == errtab[i].errnum)
972 976 return (errtab[i].errmsg);
973 977 }
974 978
975 979 return ("unknown local group error");
976 980 }
977 981
978 982 /*
979 983 * smb_lgrp_err_to_ntstatus
980 984 *
981 985 * This routine maps Local group operation errors to NT Status error codes.
982 986 */
983 987 uint32_t
984 988 smb_lgrp_err_to_ntstatus(uint32_t lgrp_err)
985 989 {
986 990 int i;
987 991 static struct err_map {
988 992 uint32_t lgrp_err;
989 993 uint32_t nt_status;
990 994 } err_map[] = {
991 995 { SMB_LGRP_SUCCESS, NT_STATUS_SUCCESS },
992 996 { SMB_LGRP_INVALID_ARG, NT_STATUS_INVALID_PARAMETER },
993 997 { SMB_LGRP_INVALID_MEMBER, NT_STATUS_INVALID_MEMBER },
994 998 { SMB_LGRP_INVALID_NAME, NT_STATUS_INVALID_PARAMETER },
995 999 { SMB_LGRP_NOT_FOUND, NT_STATUS_NO_SUCH_ALIAS },
996 1000 { SMB_LGRP_EXISTS, NT_STATUS_ALIAS_EXISTS },
997 1001 { SMB_LGRP_NO_SID, NT_STATUS_INVALID_SID },
998 1002 { SMB_LGRP_NO_LOCAL_SID, NT_STATUS_INVALID_SID },
999 1003 { SMB_LGRP_SID_NOTLOCAL, NT_STATUS_INVALID_SID },
1000 1004 { SMB_LGRP_WKSID, NT_STATUS_INVALID_SID },
1001 1005 { SMB_LGRP_NO_MEMORY, NT_STATUS_NO_MEMORY },
1002 1006 { SMB_LGRP_DB_ERROR, NT_STATUS_INTERNAL_DB_ERROR },
1003 1007 { SMB_LGRP_DBINIT_ERROR, NT_STATUS_INTERNAL_DB_ERROR },
1004 1008 { SMB_LGRP_INTERNAL_ERROR, NT_STATUS_INTERNAL_ERROR },
1005 1009 { SMB_LGRP_MEMBER_IN_GROUP, NT_STATUS_MEMBER_IN_ALIAS },
1006 1010 { SMB_LGRP_MEMBER_NOT_IN_GROUP, NT_STATUS_MEMBER_NOT_IN_ALIAS },
1007 1011 { SMB_LGRP_NO_SUCH_PRIV, NT_STATUS_NO_SUCH_PRIVILEGE },
1008 1012 { SMB_LGRP_NO_SUCH_DOMAIN, NT_STATUS_NO_SUCH_DOMAIN },
1009 1013 { SMB_LGRP_PRIV_HELD, NT_STATUS_SUCCESS },
1010 1014 { SMB_LGRP_PRIV_NOT_HELD, NT_STATUS_PRIVILEGE_NOT_HELD },
1011 1015 { SMB_LGRP_BAD_DATA, NT_STATUS_DATA_ERROR },
1012 1016 { SMB_LGRP_NO_MORE, NT_STATUS_NO_MORE_ENTRIES },
1013 1017 { SMB_LGRP_DBOPEN_FAILED, NT_STATUS_INTERNAL_DB_ERROR },
1014 1018 { SMB_LGRP_DBEXEC_FAILED, NT_STATUS_INTERNAL_DB_ERROR },
1015 1019 { SMB_LGRP_DBINIT_FAILED, NT_STATUS_INTERNAL_DB_ERROR },
1016 1020 { SMB_LGRP_DOMLKP_FAILED, NT_STATUS_INTERNAL_DB_ERROR },
1017 1021 { SMB_LGRP_DOMINS_FAILED, NT_STATUS_INTERNAL_DB_ERROR },
1018 1022 { SMB_LGRP_INSERT_FAILED, NT_STATUS_INTERNAL_DB_ERROR },
1019 1023 { SMB_LGRP_DELETE_FAILED, NT_STATUS_INTERNAL_DB_ERROR },
1020 1024 { SMB_LGRP_UPDATE_FAILED, NT_STATUS_INTERNAL_DB_ERROR },
1021 1025 { SMB_LGRP_LOOKUP_FAILED, NT_STATUS_INTERNAL_DB_ERROR },
1022 1026 { SMB_LGRP_NOT_SUPPORTED, NT_STATUS_NOT_SUPPORTED },
1023 1027 { SMB_LGRP_OFFLINE, NT_STATUS_INTERNAL_ERROR },
1024 1028 { SMB_LGRP_POSIXCREATE_FAILED, NT_STATUS_UNSUCCESSFUL }
1025 1029 };
1026 1030
1027 1031 for (i = 0; i < sizeof (err_map)/sizeof (err_map[0]); ++i) {
1028 1032 if (err_map[i].lgrp_err == lgrp_err)
1029 1033 return (err_map[i].nt_status);
1030 1034 }
1031 1035
1032 1036 return (NT_STATUS_INTERNAL_ERROR);
1033 1037 }
1034 1038
1035 1039 /*
1036 1040 * smb_lgrp_chkmember
1037 1041 *
1038 1042 * Determines valid account types for being member of
1039 1043 * a local group. We really have no business trying to
1040 1044 * keep track of the "type" of SIDs in a group, so just
1041 1045 * validate that the SID type is a known enum value.
1042 1046 */
1043 1047 static boolean_t
1044 1048 smb_lgrp_chkmember(uint16_t sid_type)
1045 1049 {
1046 1050 switch (sid_type) {
1047 1051 case SidTypeNull:
1048 1052 case SidTypeUser:
1049 1053 case SidTypeGroup:
1050 1054 case SidTypeAlias:
1051 1055 case SidTypeWellKnownGroup:
1052 1056 case SidTypeDeletedAccount:
1053 1057 case SidTypeInvalid:
1054 1058 case SidTypeUnknown:
1055 1059 return (B_TRUE);
1056 1060 }
1057 1061 return (B_FALSE);
1058 1062 }
1059 1063
1060 1064 /*
1061 1065 * smb_lgrp_start
1062 1066 *
1063 1067 * Initializes the library private global variables.
1064 1068 * Create the database, if it doesn't exist, and add
1065 1069 * the predefined builtin groups.
1066 1070 */
1067 1071 int
1068 1072 smb_lgrp_start(void)
1069 1073 {
1070 1074 static char *builtin[] = {
1071 1075 "Administrators",
1072 1076 "Backup Operators",
1073 1077 "Power Users"
1074 1078 };
1075 1079 smb_wka_t *wka;
1076 1080 char *localsid;
1077 1081 int i, rc;
1078 1082 int ngrp = sizeof (builtin) / sizeof (builtin[0]);
1079 1083
1080 1084 (void) mutex_lock(&smb_localgrp.lg_mutex);
1081 1085
1082 1086 if ((localsid = smb_config_get_localsid()) == NULL) {
1083 1087 (void) mutex_unlock(&smb_localgrp.lg_mutex);
1084 1088 return (SMB_LGRP_NO_LOCAL_SID);
1085 1089 }
1086 1090
1087 1091 smb_localgrp.lg_machine_sid = smb_sid_fromstr(localsid);
1088 1092 free(localsid);
1089 1093
1090 1094 if (!smb_sid_isvalid(smb_localgrp.lg_machine_sid)) {
1091 1095 free(smb_localgrp.lg_machine_sid);
1092 1096 smb_localgrp.lg_machine_sid = NULL;
1093 1097 (void) mutex_unlock(&smb_localgrp.lg_mutex);
1094 1098 return (SMB_LGRP_NO_LOCAL_SID);
1095 1099 }
1096 1100
1097 1101 rc = smb_lgrp_db_init();
1098 1102 if (rc != SMB_LGRP_SUCCESS) {
1099 1103 free(smb_localgrp.lg_machine_sid);
1100 1104 smb_localgrp.lg_machine_sid = NULL;
1101 1105 (void) mutex_unlock(&smb_localgrp.lg_mutex);
1102 1106 return (rc);
1103 1107 }
1104 1108
1105 1109 smb_localgrp.lg_online = B_TRUE;
1106 1110 (void) mutex_unlock(&smb_localgrp.lg_mutex);
1107 1111
1108 1112 for (i = 0; i < ngrp; i++) {
1109 1113 char *tname;
1110 1114
1111 1115 if ((wka = smb_wka_lookup_name(builtin[i])) == NULL)
1112 1116 continue;
1113 1117
1114 1118 if ((tname = strdup(wka->wka_name)) == NULL)
1115 1119 return (SMB_LGRP_NO_MEMORY);
1116 1120 if (!smb_lgrp_exists(tname)) {
1117 1121 rc = smb_lgrp_add(tname, wka->wka_desc);
1118 1122 if (rc != SMB_LGRP_SUCCESS) {
1119 1123 syslog(LOG_DEBUG, "failed to add %s",
1120 1124 tname);
1121 1125 }
1122 1126 }
1123 1127 free(tname);
1124 1128 }
1125 1129
1126 1130 return (SMB_LGRP_SUCCESS);
1127 1131 }
1128 1132
1129 1133 /*
1130 1134 * smb_lgrp_stop
1131 1135 *
1132 1136 * Unintialize the library global private variables.
1133 1137 */
1134 1138 void
1135 1139 smb_lgrp_stop(void)
1136 1140 {
1137 1141 (void) mutex_lock(&smb_localgrp.lg_mutex);
1138 1142 if (!smb_localgrp.lg_online)
1139 1143 return;
1140 1144
1141 1145 smb_localgrp.lg_online = B_FALSE;
1142 1146
1143 1147 while (smb_localgrp.lg_refcnt > 0)
1144 1148 (void) cond_wait(&smb_localgrp.lg_cv, &smb_localgrp.lg_mutex);
1145 1149
1146 1150 free(smb_localgrp.lg_machine_sid);
1147 1151 smb_localgrp.lg_machine_sid = NULL;
1148 1152 (void) mutex_unlock(&smb_localgrp.lg_mutex);
1149 1153 }
1150 1154
1151 1155 static boolean_t
1152 1156 smb_lgrp_enter(void)
1153 1157 {
1154 1158 boolean_t status;
1155 1159
1156 1160 (void) mutex_lock(&smb_localgrp.lg_mutex);
1157 1161
1158 1162 status = smb_localgrp.lg_online;
1159 1163
1160 1164 if (smb_localgrp.lg_online)
1161 1165 ++smb_localgrp.lg_refcnt;
1162 1166
1163 1167 (void) mutex_unlock(&smb_localgrp.lg_mutex);
1164 1168 return (status);
1165 1169 }
1166 1170
1167 1171 static void
1168 1172 smb_lgrp_exit(void)
1169 1173 {
1170 1174 (void) mutex_lock(&smb_localgrp.lg_mutex);
1171 1175 assert(smb_localgrp.lg_refcnt > 0);
1172 1176
1173 1177 if ((--smb_localgrp.lg_refcnt) == 0)
1174 1178 (void) cond_signal(&smb_localgrp.lg_cv);
1175 1179
1176 1180 (void) mutex_unlock(&smb_localgrp.lg_mutex);
1177 1181 }
1178 1182
1179 1183 /*
1180 1184 * smb_lgrp_db_open
1181 1185 *
1182 1186 * Opens group database with the given mode.
1183 1187 */
1184 1188 static sqlite *
1185 1189 smb_lgrp_db_open(int mode)
1186 1190 {
1187 1191 sqlite *db;
1188 1192 char *errmsg = NULL;
1189 1193
1190 1194 db = sqlite_open(SMB_LGRP_DB_NAME, mode, &errmsg);
1191 1195 if (db == NULL) {
1192 1196 syslog(LOG_ERR, "failed to open group database (%s)",
1193 1197 NULL_MSGCHK(errmsg));
1194 1198 sqlite_freemem(errmsg);
1195 1199 }
1196 1200
1197 1201 return (db);
1198 1202 }
1199 1203
1200 1204 /*
1201 1205 * smb_lgrp_db_close
1202 1206 *
1203 1207 * Closes the given database handle
1204 1208 */
1205 1209 static void
1206 1210 smb_lgrp_db_close(sqlite *db)
1207 1211 {
1208 1212 if (db) {
1209 1213 sqlite_close(db);
1210 1214 }
1211 1215 }
1212 1216
1213 1217 /*
1214 1218 * smb_lgrp_db_init
1215 1219 *
1216 1220 * Creates the group database based on the defined SQL statement.
1217 1221 * It also initializes db_info and domain tables.
1218 1222 */
1219 1223 static int
1220 1224 smb_lgrp_db_init(void)
1221 1225 {
1222 1226 int dbrc = SQLITE_OK;
1223 1227 int rc = SMB_LGRP_SUCCESS;
1224 1228 sqlite *db = NULL;
1225 1229 char *errmsg = NULL;
1226 1230
1227 1231 db = sqlite_open(SMB_LGRP_DB_NAME, 0600, &errmsg);
1228 1232 if (db == NULL) {
1229 1233 syslog(LOG_ERR, "failed to create group database (%s)",
1230 1234 NULL_MSGCHK(errmsg));
1231 1235 sqlite_freemem(errmsg);
1232 1236 return (SMB_LGRP_DBOPEN_FAILED);
1233 1237 }
1234 1238
1235 1239 sqlite_busy_timeout(db, SMB_LGRP_DB_TIMEOUT);
1236 1240 dbrc = sqlite_exec(db, "BEGIN TRANSACTION;", NULL, NULL, &errmsg);
1237 1241 if (dbrc != SQLITE_OK) {
1238 1242 syslog(LOG_DEBUG, "failed to begin database transaction (%s)",
1239 1243 NULL_MSGCHK(errmsg));
1240 1244 sqlite_freemem(errmsg);
1241 1245 sqlite_close(db);
1242 1246 return (SMB_LGRP_DBEXEC_FAILED);
1243 1247 }
1244 1248
1245 1249 switch (sqlite_exec(db, SMB_LGRP_DB_SQL, NULL, NULL, &errmsg)) {
1246 1250 case SQLITE_ERROR:
1247 1251 /*
1248 1252 * This is the normal situation: CREATE probably failed because
1249 1253 * tables already exist. It may indicate an error in SQL as well
1250 1254 * but we cannot tell.
1251 1255 */
1252 1256 sqlite_freemem(errmsg);
1253 1257 dbrc = sqlite_exec(db, "ROLLBACK TRANSACTION", NULL, NULL,
1254 1258 &errmsg);
1255 1259 rc = SMB_LGRP_SUCCESS;
1256 1260 break;
1257 1261
1258 1262 case SQLITE_OK:
1259 1263 dbrc = sqlite_exec(db, "COMMIT TRANSACTION", NULL, NULL,
1260 1264 &errmsg);
1261 1265 if (dbrc != SQLITE_OK)
1262 1266 break;
1263 1267 rc = smb_lgrp_dtbl_insert(db, NT_BUILTIN_DOMAIN_SIDSTR,
1264 1268 NULL);
1265 1269 if (rc == SMB_LGRP_SUCCESS)
1266 1270 rc = smb_lgrp_db_setinfo(db);
1267 1271 if (rc != SMB_LGRP_SUCCESS) {
1268 1272 (void) sqlite_close(db);
1269 1273 (void) unlink(SMB_LGRP_DB_NAME);
1270 1274 return (rc);
1271 1275 }
1272 1276 break;
1273 1277
1274 1278 default:
1275 1279 syslog(LOG_ERR,
1276 1280 "failed to initialize group database (%s)", errmsg);
1277 1281 sqlite_freemem(errmsg);
1278 1282 dbrc = sqlite_exec(db, "ROLLBACK TRANSACTION", NULL, NULL,
1279 1283 &errmsg);
1280 1284 rc = SMB_LGRP_DBINIT_FAILED;
1281 1285 break;
1282 1286 }
1283 1287
1284 1288 if (dbrc != SQLITE_OK) {
1285 1289 /* this is bad - database may be left in a locked state */
1286 1290 syslog(LOG_DEBUG, "failed to close a transaction (%s)",
1287 1291 NULL_MSGCHK(errmsg));
1288 1292 sqlite_freemem(errmsg);
1289 1293 }
1290 1294
1291 1295 (void) sqlite_close(db);
1292 1296 return (rc);
1293 1297 }
1294 1298
1295 1299 /*
1296 1300 * smb_lgrp_gtbl_lookup
1297 1301 *
1298 1302 * This is a flexible lookup function for the group database.
1299 1303 * The key type can be specified by the 'key' arg and the actual key
1300 1304 * values can be passed after the 'infolvl' arg. 'infolvl' arg specifies
1301 1305 * what information items for the specified group is needed.
1302 1306 *
1303 1307 * Note that the function assumes the given key is unique and only
1304 1308 * specifies one or 0 group. The keys that are supported now are
1305 1309 * the group name and the group SID
1306 1310 *
1307 1311 * Note that this function doesn't allocate the group
1308 1312 * structure itself only the fields, so the given grp
1309 1313 * pointer has to point to a group structure.
1310 1314 * Caller must free the allocated memories for the fields
1311 1315 * by calling smb_lgrp_free().
1312 1316 */
1313 1317 static int
1314 1318 smb_lgrp_gtbl_lookup(sqlite *db, int key, smb_group_t *grp, int infolvl, ...)
1315 1319 {
1316 1320 char *errmsg = NULL;
1317 1321 char *sql;
1318 1322 char **result;
1319 1323 int nrow, ncol;
1320 1324 int rc, dom_idx;
1321 1325 smb_group_t grpkey;
1322 1326 va_list ap;
1323 1327
1324 1328 if (db == NULL)
1325 1329 return (SMB_LGRP_DBOPEN_FAILED);
1326 1330
1327 1331 bzero(grp, sizeof (smb_group_t));
1328 1332 va_start(ap, infolvl);
1329 1333
1330 1334 switch (key) {
1331 1335 case SMB_LGRP_GTBL_NAME:
1332 1336 grpkey.sg_name = va_arg(ap, char *);
1333 1337 sql = sqlite_mprintf("SELECT * FROM groups WHERE name = '%s'",
1334 1338 grpkey.sg_name);
1335 1339 break;
1336 1340
1337 1341 case SMB_LGRP_GTBL_SIDRID:
1338 1342 grpkey.sg_rid = va_arg(ap, uint32_t);
1339 1343 grpkey.sg_domain = va_arg(ap, smb_domain_type_t);
1340 1344 if (grpkey.sg_domain == SMB_DOMAIN_LOCAL) {
1341 1345 dom_idx = SMB_LGRP_LOCAL_IDX;
1342 1346 /* need to map the given rid to a gid */
1343 1347 rc = smb_lgrp_getgid(grpkey.sg_rid,
1344 1348 (gid_t *)&grpkey.sg_rid);
1345 1349 if (rc != SMB_LGRP_SUCCESS) {
1346 1350 va_end(ap);
1347 1351 return (rc);
1348 1352 }
1349 1353 } else {
1350 1354 dom_idx = SMB_LGRP_BUILTIN_IDX;
1351 1355 }
1352 1356
1353 1357 sql = sqlite_mprintf("SELECT * FROM groups "
1354 1358 "WHERE (sid_idx = %d) AND (sid_rid = %u)",
1355 1359 dom_idx, grpkey.sg_rid);
1356 1360 break;
1357 1361
1358 1362 default:
1359 1363 va_end(ap);
1360 1364 return (SMB_LGRP_INVALID_ARG);
1361 1365 }
1362 1366
1363 1367 va_end(ap);
1364 1368 if (sql == NULL)
1365 1369 return (SMB_LGRP_NO_MEMORY);
1366 1370
1367 1371 rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg);
1368 1372 sqlite_freemem(sql);
1369 1373
1370 1374 if (rc != SQLITE_OK) {
1371 1375 syslog(LOG_DEBUG, "failed to lookup (%s)", NULL_MSGCHK(errmsg));
1372 1376 sqlite_freemem(errmsg);
1373 1377 return (SMB_LGRP_LOOKUP_FAILED);
1374 1378 }
1375 1379
1376 1380 if (nrow == 0) {
1377 1381 /* group not found */
1378 1382 sqlite_free_table(result);
1379 1383 return (SMB_LGRP_NOT_FOUND);
1380 1384 }
1381 1385
1382 1386 if (nrow != 1 || ncol != SMB_LGRP_GTBL_NCOL) {
1383 1387 sqlite_free_table(result);
1384 1388 return (SMB_LGRP_DB_ERROR);
1385 1389 }
1386 1390
1387 1391 rc = smb_lgrp_decode(grp, &result[SMB_LGRP_GTBL_NCOL], infolvl, db);
1388 1392 sqlite_free_table(result);
1389 1393 return (rc);
1390 1394 }
1391 1395
1392 1396 /*
1393 1397 * smb_lgrp_gtbl_exists
1394 1398 *
1395 1399 * Checks to see if the given group exists or not.
1396 1400 */
1397 1401 static boolean_t
1398 1402 smb_lgrp_gtbl_exists(sqlite *db, char *gname)
1399 1403 {
1400 1404 char *errmsg = NULL;
1401 1405 char *sql;
1402 1406 char **result;
1403 1407 int nrow, ncol;
1404 1408 int rc;
1405 1409
1406 1410 if (db == NULL)
1407 1411 return (NULL);
1408 1412
1409 1413 sql = sqlite_mprintf("SELECT name FROM groups WHERE name = '%s'",
1410 1414 gname);
1411 1415 rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg);
1412 1416 sqlite_freemem(sql);
1413 1417
1414 1418 if (rc != SQLITE_OK) {
1415 1419 syslog(LOG_DEBUG, "failed to lookup %s (%s)",
1416 1420 gname, NULL_MSGCHK(errmsg));
1417 1421 sqlite_freemem(errmsg);
1418 1422 return (B_FALSE);
1419 1423 }
1420 1424
1421 1425 sqlite_free_table(result);
1422 1426 return (nrow != 0);
1423 1427 }
1424 1428
1425 1429 /*
1426 1430 * smb_lgrp_gtbl_count
1427 1431 *
1428 1432 * Counts the number of groups in the domain specified by
1429 1433 * 'dom_idx'
1430 1434 */
1431 1435 static int
1432 1436 smb_lgrp_gtbl_count(sqlite *db, int dom_idx, int *count)
1433 1437 {
1434 1438 char *errmsg = NULL;
1435 1439 char *sql;
1436 1440 char **result;
1437 1441 int nrow, ncol;
1438 1442 int rc;
1439 1443
1440 1444 *count = 0;
1441 1445 if (db == NULL)
1442 1446 return (SMB_LGRP_DBOPEN_FAILED);
1443 1447
1444 1448 sql = sqlite_mprintf("SELECT sid_idx FROM groups WHERE sid_idx = %d",
1445 1449 dom_idx);
1446 1450 rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg);
1447 1451 sqlite_freemem(sql);
1448 1452
1449 1453 if (rc != SQLITE_OK) {
1450 1454 syslog(LOG_DEBUG, "failed to count (%s)", NULL_MSGCHK(errmsg));
1451 1455 sqlite_freemem(errmsg);
1452 1456 return (SMB_LGRP_LOOKUP_FAILED);
1453 1457 }
1454 1458
1455 1459 sqlite_free_table(result);
1456 1460 if (ncol > 1)
1457 1461 return (SMB_LGRP_DB_ERROR);
1458 1462
1459 1463 *count = nrow;
1460 1464 return (SMB_LGRP_SUCCESS);
1461 1465 }
1462 1466
1463 1467 /*
1464 1468 * smb_lgrp_gtbl_insert
1465 1469 *
1466 1470 * Insert a record for the given group in the group database.
1467 1471 *
1468 1472 * NOTE: this function assumes that this group has no members
1469 1473 * at this time.
1470 1474 */
1471 1475 static int
1472 1476 smb_lgrp_gtbl_insert(sqlite *db, smb_group_t *grp)
1473 1477 {
1474 1478 smb_lgpid_t privs[SE_MAX_LUID + 1];
1475 1479 smb_lgplist_t plist;
1476 1480 char *errmsg = NULL;
1477 1481 char *sql;
1478 1482 int dom_idx;
1479 1483 int rc;
1480 1484
1481 1485 if (db == NULL)
1482 1486 return (SMB_LGRP_DBOPEN_FAILED);
1483 1487
1484 1488 dom_idx = (grp->sg_domain == SMB_DOMAIN_LOCAL)
1485 1489 ? SMB_LGRP_LOCAL_IDX : SMB_LGRP_BUILTIN_IDX;
1486 1490
1487 1491 plist.p_cnt = SE_MAX_LUID;
1488 1492 plist.p_ids = privs;
1489 1493 smb_lgrp_encode_privset(grp, &plist);
1490 1494
1491 1495 sql = sqlite_mprintf("INSERT INTO groups "
1492 1496 "(name, sid_idx, sid_rid, sid_type, sid_attrs, comment, "
1493 1497 "n_privs, privs, n_members, members) "
1494 1498 "VALUES('%s', %u, %u, %u, %u, '%q', %u, '%q', %u, '%q')",
1495 1499 grp->sg_name, dom_idx, grp->sg_rid, grp->sg_id.gs_type,
1496 1500 grp->sg_attr, (grp->sg_cmnt) ? grp->sg_cmnt : "",
1497 1501 plist.p_cnt, (char *)plist.p_ids, 0, "");
1498 1502
1499 1503 if (sql == NULL)
1500 1504 return (SMB_LGRP_NO_MEMORY);
1501 1505
1502 1506 rc = sqlite_exec(db, sql, NULL, NULL, &errmsg);
1503 1507 sqlite_freemem(sql);
1504 1508
1505 1509 if (rc != SQLITE_OK) {
1506 1510 syslog(LOG_DEBUG, "failed to insert %s (%s)",
1507 1511 grp->sg_name, NULL_MSGCHK(errmsg));
1508 1512 sqlite_freemem(errmsg);
1509 1513 rc = SMB_LGRP_INSERT_FAILED;
1510 1514 } else {
1511 1515 rc = SMB_LGRP_SUCCESS;
1512 1516 }
1513 1517
1514 1518 return (rc);
1515 1519 }
1516 1520
1517 1521 /*
1518 1522 * smb_lgrp_gtbl_delete
1519 1523 *
1520 1524 * Removes the specified group from the database
1521 1525 */
1522 1526 static int
1523 1527 smb_lgrp_gtbl_delete(sqlite *db, char *gname)
1524 1528 {
1525 1529 char *errmsg = NULL;
1526 1530 char *sql;
1527 1531 int rc;
1528 1532
1529 1533 if (db == NULL)
1530 1534 return (SMB_LGRP_DBOPEN_FAILED);
1531 1535
1532 1536 sql = sqlite_mprintf("DELETE FROM groups WHERE name = '%s'", gname);
1533 1537 if (sql == NULL)
1534 1538 return (SMB_LGRP_NO_MEMORY);
1535 1539
1536 1540 rc = sqlite_exec(db, sql, NULL, NULL, &errmsg);
1537 1541 sqlite_freemem(sql);
1538 1542
1539 1543 if (rc != SQLITE_OK) {
1540 1544 syslog(LOG_DEBUG, "failed to delete %s (%s)",
1541 1545 gname, NULL_MSGCHK(errmsg));
1542 1546 sqlite_freemem(errmsg);
1543 1547 rc = SMB_LGRP_DELETE_FAILED;
1544 1548 } else {
1545 1549 rc = SMB_LGRP_SUCCESS;
1546 1550 }
1547 1551
1548 1552 return (rc);
1549 1553 }
1550 1554
1551 1555 /*
1552 1556 * smb_lgrp_gtbl_update
1553 1557 *
1554 1558 * Updates the specified group information, the supported items
1555 1559 * are group name and comment
1556 1560 */
1557 1561 static int
1558 1562 smb_lgrp_gtbl_update(sqlite *db, char *gname, smb_group_t *grp, int col_id)
1559 1563 {
1560 1564 char *errmsg = NULL;
1561 1565 char *sql;
1562 1566 int rc;
1563 1567
1564 1568 if (db == NULL)
1565 1569 return (SMB_LGRP_DBOPEN_FAILED);
1566 1570
1567 1571 /* UPDATE doesn't fail if gname doesn't exist */
1568 1572 if (!smb_lgrp_gtbl_exists(db, gname))
1569 1573 return (SMB_LGRP_NOT_FOUND);
1570 1574
1571 1575 switch (col_id) {
1572 1576 case SMB_LGRP_GTBL_NAME:
1573 1577 if (smb_lgrp_gtbl_exists(db, grp->sg_name))
1574 1578 return (SMB_LGRP_EXISTS);
1575 1579 sql = sqlite_mprintf("UPDATE groups SET name = '%s' "
1576 1580 "WHERE name = '%s'", grp->sg_name, gname);
1577 1581 break;
1578 1582
1579 1583 case SMB_LGRP_GTBL_CMNT:
1580 1584 sql = sqlite_mprintf("UPDATE groups SET comment = '%q' "
1581 1585 "WHERE name = '%s'", grp->sg_cmnt, gname);
1582 1586 break;
1583 1587
1584 1588 default:
1585 1589 return (SMB_LGRP_INVALID_ARG);
1586 1590 }
1587 1591
1588 1592 if (sql == NULL)
1589 1593 return (SMB_LGRP_NO_MEMORY);
1590 1594
1591 1595 rc = sqlite_exec(db, sql, NULL, NULL, &errmsg);
1592 1596 sqlite_freemem(sql);
1593 1597
1594 1598 if (rc != SQLITE_OK) {
1595 1599 syslog(LOG_DEBUG, "failed to update %s (%s)",
1596 1600 gname, NULL_MSGCHK(errmsg));
1597 1601 sqlite_freemem(errmsg);
1598 1602 rc = SMB_LGRP_UPDATE_FAILED;
1599 1603 } else {
1600 1604 rc = SMB_LGRP_SUCCESS;
1601 1605 }
1602 1606
1603 1607 return (rc);
1604 1608 }
1605 1609
1606 1610 /*
1607 1611 * smb_lgrp_gtbl_update_mlist
1608 1612 *
1609 1613 * Adds/removes the specified member from the member list of the
1610 1614 * given group
1611 1615 */
1612 1616 static int
1613 1617 smb_lgrp_gtbl_update_mlist(sqlite *db, char *gname, smb_gsid_t *member,
1614 1618 int flags)
1615 1619 {
1616 1620 smb_lgmlist_t new_members;
1617 1621 smb_lgmlist_t members;
1618 1622 smb_lgmid_t mid;
1619 1623 char *errmsg = NULL;
1620 1624 char *sql;
1621 1625 char **result;
1622 1626 int nrow, ncol;
1623 1627 int rc;
1624 1628
1625 1629 if (db == NULL)
1626 1630 return (SMB_LGRP_DBOPEN_FAILED);
1627 1631
1628 1632 sql = sqlite_mprintf("SELECT n_members, members FROM groups "
1629 1633 "WHERE name = '%s'", gname);
1630 1634
1631 1635 if (sql == NULL)
1632 1636 return (SMB_LGRP_NO_MEMORY);
1633 1637
1634 1638 rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg);
1635 1639 sqlite_freemem(sql);
1636 1640
1637 1641 if (rc != SQLITE_OK) {
1638 1642 syslog(LOG_DEBUG, "failed to lookup %s (%s)",
1639 1643 gname, NULL_MSGCHK(errmsg));
1640 1644 sqlite_freemem(errmsg);
1641 1645 return (SMB_LGRP_LOOKUP_FAILED);
1642 1646 }
1643 1647
1644 1648 if (nrow == 0) {
1645 1649 /* group not found */
1646 1650 sqlite_free_table(result);
1647 1651 return (SMB_LGRP_NOT_FOUND);
1648 1652 }
1649 1653
1650 1654 if (nrow != 1 || ncol != 2) {
1651 1655 sqlite_free_table(result);
1652 1656 return (SMB_LGRP_DB_ERROR);
1653 1657 }
1654 1658
1655 1659 bzero(&mid, sizeof (mid));
1656 1660 mid.m_type = member->gs_type;
1657 1661 rc = smb_lgrp_dtbl_getidx(db, member->gs_sid, mid.m_type,
1658 1662 &mid.m_idx, &mid.m_rid);
1659 1663 if (rc != SMB_LGRP_SUCCESS) {
1660 1664 sqlite_free_table(result);
1661 1665 return (rc);
1662 1666 }
1663 1667
1664 1668 members.m_cnt = atoi(result[2]);
1665 1669 members.m_ids = result[3];
1666 1670
1667 1671 switch (flags) {
1668 1672 case SMB_LGRP_DB_ADDMEMBER:
1669 1673 rc = smb_lgrp_mlist_add(&members, &mid, &new_members);
1670 1674 break;
1671 1675 case SMB_LGRP_DB_DELMEMBER:
1672 1676 rc = smb_lgrp_mlist_del(&members, &mid, &new_members);
1673 1677 break;
1674 1678 default:
1675 1679 rc = SMB_LGRP_INVALID_ARG;
1676 1680 }
1677 1681
1678 1682 sqlite_free_table(result);
1679 1683 if (rc != SMB_LGRP_SUCCESS)
1680 1684 return (rc);
1681 1685
1682 1686 sql = sqlite_mprintf("UPDATE groups SET n_members = %u, members = '%s'"
1683 1687 " WHERE name = '%s'", new_members.m_cnt, new_members.m_ids, gname);
1684 1688
1685 1689 free(new_members.m_ids);
1686 1690
1687 1691 if (sql == NULL)
1688 1692 return (SMB_LGRP_NO_MEMORY);
1689 1693
1690 1694 rc = sqlite_exec(db, sql, NULL, NULL, &errmsg);
1691 1695 sqlite_freemem(sql);
1692 1696
1693 1697 if (rc != SQLITE_OK) {
1694 1698 syslog(LOG_DEBUG, "failed to update %s (%s)", gname,
1695 1699 NULL_MSGCHK(errmsg));
1696 1700 sqlite_freemem(errmsg);
1697 1701 rc = SMB_LGRP_UPDATE_FAILED;
1698 1702 } else {
1699 1703 rc = SMB_LGRP_SUCCESS;
1700 1704 }
1701 1705
1702 1706 return (rc);
1703 1707 }
1704 1708
1705 1709 /*
1706 1710 * smb_lgrp_gtbl_update_plist
1707 1711 *
1708 1712 * Adds/removes the specified privilege from the privilege list of the
1709 1713 * given group
1710 1714 */
1711 1715 static int
1712 1716 smb_lgrp_gtbl_update_plist(sqlite *db, char *gname, uint8_t priv_id,
1713 1717 boolean_t enable)
1714 1718 {
1715 1719 char *sql;
1716 1720 char *errmsg = NULL;
1717 1721 char **result;
1718 1722 int nrow, ncol;
1719 1723 int rc;
1720 1724 smb_lgplist_t privs;
1721 1725 smb_lgplist_t new_privs;
1722 1726
1723 1727 if (db == NULL)
1724 1728 return (SMB_LGRP_DBOPEN_FAILED);
1725 1729
1726 1730 sql = sqlite_mprintf("SELECT n_privs, privs FROM groups "
1727 1731 "WHERE name = '%s'", gname);
1728 1732
1729 1733 if (sql == NULL)
1730 1734 return (SMB_LGRP_NO_MEMORY);
1731 1735
1732 1736 rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg);
1733 1737 sqlite_freemem(sql);
1734 1738
1735 1739 if (rc != SQLITE_OK) {
1736 1740 syslog(LOG_DEBUG, "failed to lookup %s (%s)",
1737 1741 gname, NULL_MSGCHK(errmsg));
1738 1742 sqlite_freemem(errmsg);
1739 1743 return (SMB_LGRP_LOOKUP_FAILED);
1740 1744 }
1741 1745
1742 1746 if (nrow == 0) {
1743 1747 /* group not found */
1744 1748 sqlite_free_table(result);
1745 1749 return (SMB_LGRP_NOT_FOUND);
1746 1750 }
1747 1751
1748 1752 if (nrow != 1 || ncol != 2) {
1749 1753 sqlite_free_table(result);
1750 1754 return (SMB_LGRP_DB_ERROR);
1751 1755 }
1752 1756
1753 1757 privs.p_cnt = atoi(result[2]);
1754 1758 privs.p_ids = (smb_lgpid_t *)result[3];
1755 1759
1756 1760 if (enable)
1757 1761 rc = smb_lgrp_plist_add(&privs, priv_id, &new_privs);
1758 1762 else
1759 1763 rc = smb_lgrp_plist_del(&privs, priv_id, &new_privs);
1760 1764
1761 1765 sqlite_free_table(result);
1762 1766 if (rc != SMB_LGRP_SUCCESS)
1763 1767 return (rc);
1764 1768
1765 1769 sql = sqlite_mprintf("UPDATE groups SET n_privs = %u, privs = '%q'"
1766 1770 " WHERE name = '%s'", new_privs.p_cnt, (char *)new_privs.p_ids,
1767 1771 gname);
1768 1772
1769 1773 free(new_privs.p_ids);
1770 1774
1771 1775 if (sql == NULL)
1772 1776 return (SMB_LGRP_NO_MEMORY);
1773 1777
1774 1778 rc = sqlite_exec(db, sql, NULL, NULL, &errmsg);
1775 1779 sqlite_freemem(sql);
1776 1780
1777 1781 if (rc != SQLITE_OK) {
1778 1782 syslog(LOG_DEBUG, "failed to update %s (%s)",
1779 1783 gname, NULL_MSGCHK(errmsg));
1780 1784 sqlite_freemem(errmsg);
1781 1785 rc = SMB_LGRP_UPDATE_FAILED;
1782 1786 } else {
1783 1787 rc = SMB_LGRP_SUCCESS;
1784 1788 }
1785 1789
1786 1790 return (rc);
1787 1791 }
1788 1792
1789 1793 /*
1790 1794 * smb_lgrp_dtbl_insert
1791 1795 *
1792 1796 * Inserts the specified domain SID in the dmain table.
1793 1797 * Upon successful insert the index will be returned in
1794 1798 * 'dom_idx' arg.
1795 1799 */
1796 1800 static int
1797 1801 smb_lgrp_dtbl_insert(sqlite *db, char *dom_sid, uint32_t *dom_idx)
1798 1802 {
1799 1803 char *errmsg = NULL;
1800 1804 char *sql;
1801 1805 int rc;
1802 1806
1803 1807 sql = sqlite_mprintf("INSERT INTO domains (dom_sid, dom_cnt)"
1804 1808 " VALUES('%s', 1);", dom_sid);
1805 1809 if (sql == NULL)
1806 1810 return (SMB_LGRP_NO_MEMORY);
1807 1811
1808 1812 rc = sqlite_exec(db, sql, NULL, NULL, &errmsg);
1809 1813 sqlite_freemem(sql);
1810 1814
1811 1815 if (rc != SQLITE_OK) {
1812 1816 syslog(LOG_DEBUG, "failed to insert domain SID (%s)",
1813 1817 NULL_MSGCHK(errmsg));
1814 1818 sqlite_freemem(errmsg);
1815 1819 return (SMB_LGRP_DOMINS_FAILED);
1816 1820 }
1817 1821
1818 1822 if (dom_idx)
1819 1823 *dom_idx = sqlite_last_insert_rowid(db);
1820 1824 return (SMB_LGRP_SUCCESS);
1821 1825 }
1822 1826
1823 1827 /*
1824 1828 * smb_lgrp_dtbl_getidx
1825 1829 *
1826 1830 * Searches the domain table for the domain SID of the
1827 1831 * given member SID. If it finds the domain SID it'll
1828 1832 * return the index and the RID, otherwise it'll insert
1829 1833 * it in the domain table as a new SID.
1830 1834 */
1831 1835 static int
1832 1836 smb_lgrp_dtbl_getidx(sqlite *db, smb_sid_t *sid, uint16_t sid_type,
1833 1837 uint32_t *dom_idx, uint32_t *rid)
1834 1838 {
1835 1839 char sidstr[SMB_SID_STRSZ];
1836 1840 smb_sid_t *dom_sid;
1837 1841 char **result;
1838 1842 int nrow, ncol;
1839 1843 char *errmsg = NULL;
1840 1844 char *sql;
1841 1845 int rc;
1842 1846
1843 1847 if (smb_sid_indomain(smb_localgrp.lg_machine_sid, sid)) {
1844 1848 /* This is a local SID */
1845 1849 int id_type = (sid_type == SidTypeUser)
1846 1850 ? SMB_IDMAP_USER : SMB_IDMAP_GROUP;
1847 1851 *dom_idx = SMB_LGRP_LOCAL_IDX;
1848 1852 if (smb_idmap_getid(sid, rid, &id_type) != IDMAP_SUCCESS)
1849 1853 return (SMB_LGRP_INTERNAL_ERROR);
1850 1854
1851 1855 return (SMB_LGRP_SUCCESS);
1852 1856 }
1853 1857
1854 1858 if ((dom_sid = smb_sid_split(sid, rid)) == NULL)
1855 1859 return (SMB_LGRP_NO_MEMORY);
1856 1860
1857 1861 smb_sid_tostr(dom_sid, sidstr);
1858 1862 free(dom_sid);
1859 1863
1860 1864 sql = sqlite_mprintf("SELECT dom_idx FROM domains WHERE dom_sid = '%s'",
1861 1865 sidstr);
1862 1866 if (sql == NULL)
1863 1867 return (SMB_LGRP_NO_MEMORY);
1864 1868
1865 1869 rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg);
1866 1870 sqlite_freemem(sql);
1867 1871
1868 1872 if (rc != SQLITE_OK) {
1869 1873 syslog(LOG_DEBUG, "failed to lookup domain SID (%s)",
1870 1874 NULL_MSGCHK(errmsg));
1871 1875 sqlite_freemem(errmsg);
1872 1876 return (SMB_LGRP_DOMLKP_FAILED);
1873 1877 }
1874 1878
1875 1879 switch (nrow) {
1876 1880 case 0:
1877 1881 /* new domain SID; insert it into the domains table */
1878 1882 sqlite_free_table(result);
1879 1883 return (smb_lgrp_dtbl_insert(db, sidstr, dom_idx));
1880 1884
1881 1885 case 1:
1882 1886 *dom_idx = atoi(result[1]);
1883 1887 sqlite_free_table(result);
1884 1888 return (SMB_LGRP_SUCCESS);
1885 1889 }
1886 1890
1887 1891 sqlite_free_table(result);
1888 1892 return (SMB_LGRP_DB_ERROR);
1889 1893 }
1890 1894
1891 1895 /*
1892 1896 * smb_lgrp_dtbl_getsid
1893 1897 *
1894 1898 * Searchs the domain table for the given domain index.
1895 1899 * Converts the found domain SID to binary format and
1896 1900 * returns it in the 'sid' arg.
1897 1901 *
1898 1902 * Caller must free the returned SID by calling free().
1899 1903 */
1900 1904 static int
1901 1905 smb_lgrp_dtbl_getsid(sqlite *db, uint32_t dom_idx, smb_sid_t **sid)
1902 1906 {
1903 1907 char **result;
1904 1908 int nrow, ncol;
1905 1909 char *errmsg = NULL;
1906 1910 char *sql;
1907 1911 int rc;
1908 1912
1909 1913 sql = sqlite_mprintf("SELECT dom_sid FROM domains WHERE dom_idx = %u",
1910 1914 dom_idx);
1911 1915 if (sql == NULL)
1912 1916 return (SMB_LGRP_NO_MEMORY);
1913 1917
1914 1918 rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg);
1915 1919 sqlite_freemem(sql);
1916 1920
1917 1921 if (rc != SQLITE_OK) {
1918 1922 syslog(LOG_DEBUG, "failed to lookup domain index (%s)",
1919 1923 NULL_MSGCHK(errmsg));
1920 1924 sqlite_freemem(errmsg);
1921 1925 return (SMB_LGRP_DOMLKP_FAILED);
1922 1926 }
1923 1927
1924 1928 switch (nrow) {
1925 1929 case 0:
1926 1930 rc = SMB_LGRP_NO_SUCH_DOMAIN;
1927 1931 break;
1928 1932
1929 1933 case 1:
1930 1934 *sid = smb_sid_fromstr(result[1]);
1931 1935 rc = (*sid == NULL)
1932 1936 ? SMB_LGRP_INTERNAL_ERROR : SMB_LGRP_SUCCESS;
1933 1937 break;
1934 1938
1935 1939 default:
1936 1940 rc = SMB_LGRP_DB_ERROR;
1937 1941 break;
1938 1942 }
1939 1943
1940 1944 sqlite_free_table(result);
1941 1945 return (rc);
1942 1946 }
1943 1947
1944 1948 /*
1945 1949 * smb_lgrp_db_setinfo
1946 1950 *
1947 1951 * Initializes the db_info table upon database creation.
1948 1952 */
1949 1953 static int
1950 1954 smb_lgrp_db_setinfo(sqlite *db)
1951 1955 {
1952 1956 char *errmsg = NULL;
1953 1957 char *sql;
1954 1958 int rc;
1955 1959
1956 1960 sql = sqlite_mprintf("INSERT INTO db_info (ver_major, ver_minor,"
1957 1961 " magic) VALUES (%d, %d, %u)", SMB_LGRP_DB_VERMAJOR,
1958 1962 SMB_LGRP_DB_VERMINOR, SMB_LGRP_DB_MAGIC);
1959 1963
1960 1964 if (sql == NULL)
1961 1965 return (SMB_LGRP_NO_MEMORY);
1962 1966
1963 1967 rc = sqlite_exec(db, sql, NULL, NULL, &errmsg);
1964 1968 sqlite_freemem(sql);
1965 1969 if (rc != SQLITE_OK) {
1966 1970 syslog(LOG_DEBUG, "failed to insert database information (%s)",
1967 1971 NULL_MSGCHK(errmsg));
1968 1972 sqlite_freemem(errmsg);
1969 1973 rc = SMB_LGRP_DBINIT_ERROR;
1970 1974 } else {
1971 1975 rc = SMB_LGRP_SUCCESS;
1972 1976 }
1973 1977
1974 1978 return (rc);
1975 1979 }
1976 1980
1977 1981 /*
1978 1982 * smb_lgrp_mlist_add
1979 1983 *
1980 1984 * Adds the given member (newm) to the input member list (in_members)
1981 1985 * if it's not already there. The result list will be returned in
1982 1986 * out_members. The caller must free the allocated memory for
1983 1987 * out_members by calling free().
1984 1988 *
1985 1989 * in_members and out_members are hex strings.
1986 1990 */
1987 1991 static int
1988 1992 smb_lgrp_mlist_add(smb_lgmlist_t *in_members, smb_lgmid_t *newm,
1989 1993 smb_lgmlist_t *out_members)
1990 1994 {
1991 1995 char mid_hex[SMB_LGRP_MID_HEXSZ];
1992 1996 char *in_list;
1993 1997 char *out_list;
1994 1998 int in_size;
1995 1999 int out_size;
1996 2000 int mid_hexsz;
1997 2001 int i;
1998 2002
1999 2003 out_members->m_cnt = 0;
2000 2004 out_members->m_ids = NULL;
2001 2005
2002 2006 bzero(mid_hex, sizeof (mid_hex));
2003 2007 mid_hexsz = bintohex((const char *)newm, sizeof (smb_lgmid_t),
2004 2008 mid_hex, sizeof (mid_hex));
2005 2009
2006 2010 /*
2007 2011 * Check to see if this is already a group member
2008 2012 */
2009 2013 in_list = in_members->m_ids;
2010 2014 for (i = 0; i < in_members->m_cnt; i++) {
2011 2015 if (strncmp(in_list, mid_hex, mid_hexsz) == 0)
2012 2016 return (SMB_LGRP_MEMBER_IN_GROUP);
2013 2017 in_list += mid_hexsz;
2014 2018 }
2015 2019
2016 2020 in_size = (in_members->m_ids) ? strlen(in_members->m_ids) : 0;
2017 2021 out_size = in_size + sizeof (mid_hex) + 1;
2018 2022 out_list = malloc(out_size);
2019 2023 if (out_list == NULL)
2020 2024 return (SMB_LGRP_NO_MEMORY);
2021 2025
2022 2026 bzero(out_list, out_size);
2023 2027 if (in_members->m_ids)
2024 2028 (void) strlcpy(out_list, in_members->m_ids, out_size);
2025 2029 (void) strcat(out_list, mid_hex);
2026 2030
2027 2031 out_members->m_cnt = in_members->m_cnt + 1;
2028 2032 out_members->m_ids = out_list;
2029 2033
2030 2034 return (SMB_LGRP_SUCCESS);
2031 2035 }
|
↓ open down ↓ |
1875 lines elided |
↑ open up ↑ |
2032 2036
2033 2037 /*
2034 2038 * smb_lgrp_mlist_del
2035 2039 *
2036 2040 * Removes the given member (msid) from the input member list
2037 2041 * (in_members) if it's already there. The result list will b
2038 2042 * returned in out_members. The caller must free the allocated
2039 2043 * memory for out_members by calling free().
2040 2044 *
2041 2045 * in_members and out_members are hex strings.
2046 + *
2047 + * Note that we ignore the SID "type" when matching because
2048 + * we always want to delete when the SID part matches.
2049 + * The "type" part can be fiction.
2042 2050 */
2043 2051 static int
2044 2052 smb_lgrp_mlist_del(smb_lgmlist_t *in_members, smb_lgmid_t *mid,
2045 2053 smb_lgmlist_t *out_members)
2046 2054 {
2047 2055 char mid_hex[SMB_LGRP_MID_HEXSZ];
2048 2056 char *in_list;
2049 2057 char *out_list;
2050 2058 int in_size;
2051 2059 int out_size;
2052 2060 int mid_hexsz;
2053 2061 int out_cnt;
2054 2062 int i;
2055 2063
2056 2064 out_members->m_cnt = 0;
2057 2065 out_members->m_ids = NULL;
2058 2066
2059 2067 if ((in_members == NULL) || (in_members->m_cnt == 0))
2060 2068 return (SMB_LGRP_MEMBER_NOT_IN_GROUP);
2061 2069
2062 2070 in_size = strlen(in_members->m_ids);
2063 2071 out_size = in_size + sizeof (mid_hex) + 1;
2064 2072 out_list = malloc(out_size);
2065 2073 if (out_list == NULL)
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
2066 2074 return (SMB_LGRP_NO_MEMORY);
2067 2075
2068 2076 *out_list = '\0';
2069 2077
2070 2078 bzero(mid_hex, sizeof (mid_hex));
2071 2079 mid_hexsz = bintohex((const char *)mid, sizeof (smb_lgmid_t),
2072 2080 mid_hex, sizeof (mid_hex));
2073 2081
2074 2082 in_list = in_members->m_ids;
2075 2083 for (i = 0, out_cnt = 0; i < in_members->m_cnt; i++) {
2076 - if (strncmp(in_list, mid_hex, mid_hexsz)) {
2084 + /* Keep only those NOT matching in IDX,RID */
2085 + if (strncmp(in_list, mid_hex, SMB_LGRP_IDXRID_LEN)) {
2077 2086 (void) strncat(out_list, in_list, mid_hexsz);
2078 2087 out_cnt++;
2079 2088 }
2080 2089 in_list += mid_hexsz;
2081 2090 }
2082 2091
2083 2092 if (out_cnt == in_members->m_cnt) {
2084 2093 free(out_list);
2085 2094 return (SMB_LGRP_MEMBER_NOT_IN_GROUP);
2086 2095 }
2087 2096
2088 2097 out_members->m_cnt = out_cnt;
2089 2098 out_members->m_ids = out_list;
2090 2099 return (SMB_LGRP_SUCCESS);
2091 2100 }
2092 2101
2093 2102 /*
2094 2103 * smb_lgrp_plist_add
2095 2104 *
2096 2105 * Adds the given privilege to the input list (in_privs)
2097 2106 * if it's not already there. The result list is returned
2098 2107 * in out_privs. The caller must free the allocated memory
2099 2108 * for out_privs by calling free().
2100 2109 */
2101 2110 static int
2102 2111 smb_lgrp_plist_add(smb_lgplist_t *in_privs, smb_lgpid_t priv_id,
2103 2112 smb_lgplist_t *out_privs)
2104 2113 {
2105 2114 int i, size;
2106 2115 smb_lgpid_t *pbuf;
2107 2116
2108 2117 out_privs->p_cnt = 0;
2109 2118 out_privs->p_ids = NULL;
2110 2119
2111 2120 for (i = 0; i < in_privs->p_cnt; i++) {
2112 2121 if (in_privs->p_ids[i] == priv_id)
2113 2122 return (SMB_LGRP_PRIV_HELD);
2114 2123 }
2115 2124
2116 2125 size = (in_privs->p_cnt + 1) * sizeof (smb_lgpid_t) + 1;
2117 2126 pbuf = malloc(size);
2118 2127 if (pbuf == NULL)
2119 2128 return (SMB_LGRP_NO_MEMORY);
2120 2129
2121 2130 bzero(pbuf, size);
2122 2131 bcopy(in_privs->p_ids, pbuf, in_privs->p_cnt * sizeof (smb_lgpid_t));
2123 2132 pbuf[in_privs->p_cnt] = priv_id;
2124 2133
2125 2134 out_privs->p_cnt = in_privs->p_cnt + 1;
2126 2135 out_privs->p_ids = pbuf;
2127 2136
2128 2137 return (SMB_LGRP_SUCCESS);
2129 2138 }
2130 2139
2131 2140 /*
2132 2141 * smb_lgrp_plist_del
2133 2142 *
2134 2143 * Removes the given privilege from the input list (in_privs)
2135 2144 * if it's already there. The result list is returned
2136 2145 * in out_privs. The caller must free the allocated memory
2137 2146 * for out_privs by calling free().
2138 2147 */
2139 2148 static int
2140 2149 smb_lgrp_plist_del(smb_lgplist_t *in_privs, smb_lgpid_t priv_id,
2141 2150 smb_lgplist_t *out_privs)
2142 2151 {
2143 2152 int i, size;
2144 2153
2145 2154 out_privs->p_cnt = 0;
2146 2155 out_privs->p_ids = NULL;
2147 2156
2148 2157 if ((in_privs == NULL) || (in_privs->p_cnt == 0))
2149 2158 return (SMB_LGRP_PRIV_NOT_HELD);
2150 2159
2151 2160 size = (in_privs->p_cnt - 1) * sizeof (smb_lgpid_t) + 1;
2152 2161 out_privs->p_ids = malloc(size);
2153 2162 if (out_privs->p_ids == NULL)
2154 2163 return (SMB_LGRP_NO_MEMORY);
2155 2164
2156 2165 bzero(out_privs->p_ids, size);
2157 2166
2158 2167 for (i = 0; i < in_privs->p_cnt; i++) {
2159 2168 if (in_privs->p_ids[i] != priv_id)
2160 2169 out_privs->p_ids[out_privs->p_cnt++] =
2161 2170 in_privs->p_ids[i];
2162 2171 }
2163 2172
2164 2173 if (out_privs->p_cnt == in_privs->p_cnt) {
2165 2174 free(out_privs->p_ids);
2166 2175 out_privs->p_cnt = 0;
2167 2176 out_privs->p_ids = NULL;
2168 2177 return (SMB_LGRP_PRIV_NOT_HELD);
2169 2178 }
2170 2179
2171 2180 return (SMB_LGRP_SUCCESS);
2172 2181 }
2173 2182
2174 2183 /*
2175 2184 * smb_lgrp_encode_privset
2176 2185 *
2177 2186 * Encodes given privilege set into a buffer to be stored in the group
2178 2187 * database. Each entry of the encoded buffer contains the privilege ID
2179 2188 * of an enable privilege. The returned buffer is null-terminated.
2180 2189 */
2181 2190 static void
2182 2191 smb_lgrp_encode_privset(smb_group_t *grp, smb_lgplist_t *plist)
2183 2192 {
2184 2193 smb_privset_t *privs;
2185 2194 uint32_t pcnt = plist->p_cnt;
2186 2195 int i;
2187 2196
2188 2197 bzero(plist->p_ids, sizeof (smb_lgpid_t) * plist->p_cnt);
2189 2198 plist->p_cnt = 0;
2190 2199
2191 2200 privs = grp->sg_privs;
2192 2201 if ((privs == NULL) || (privs->priv_cnt == 0))
2193 2202 return;
2194 2203
2195 2204 if (pcnt < privs->priv_cnt) {
2196 2205 assert(0);
2197 2206 }
2198 2207
2199 2208 for (i = 0; i < privs->priv_cnt; i++) {
2200 2209 if (privs->priv[i].attrs == SE_PRIVILEGE_ENABLED) {
2201 2210 plist->p_ids[plist->p_cnt++] =
2202 2211 (uint8_t)privs->priv[i].luid.lo_part;
2203 2212 }
2204 2213 }
2205 2214 }
2206 2215
2207 2216 /*
2208 2217 * smb_lgrp_decode_privset
2209 2218 *
2210 2219 * Decodes the privilege information read from group table
2211 2220 * (nprivs, privs) into a binray format specified by the
2212 2221 * privilege field of smb_group_t
2213 2222 */
2214 2223 static int
2215 2224 smb_lgrp_decode_privset(smb_group_t *grp, char *nprivs, char *privs)
2216 2225 {
2217 2226 smb_lgplist_t plist;
2218 2227 int i;
2219 2228
2220 2229 plist.p_cnt = atoi(nprivs);
2221 2230 if (strlen(privs) != plist.p_cnt)
2222 2231 return (SMB_LGRP_BAD_DATA);
2223 2232
2224 2233 plist.p_ids = (smb_lgpid_t *)privs;
2225 2234 grp->sg_privs = smb_privset_new();
2226 2235 if (grp->sg_privs == NULL)
2227 2236 return (SMB_LGRP_NO_MEMORY);
2228 2237
2229 2238 for (i = 0; i < plist.p_cnt; i++)
2230 2239 smb_privset_enable(grp->sg_privs, plist.p_ids[i]);
2231 2240
2232 2241 return (SMB_LGRP_SUCCESS);
2233 2242 }
2234 2243
2235 2244 /*
2236 2245 * smb_lgrp_decode_members
2237 2246 *
2238 2247 * Decodes the members information read from group table
2239 2248 * (nmembers, members) into a binary format specified by the
2240 2249 * member fields of smb_group_t
2241 2250 */
2242 2251 static int
2243 2252 smb_lgrp_decode_members(smb_group_t *grp, char *nmembers, char *members,
2244 2253 sqlite *db)
2245 2254 {
2246 2255 smb_lgmid_t *m_id;
2247 2256 smb_lgmid_t *m_ids;
2248 2257 smb_gsid_t *m_sid;
2249 2258 smb_gsid_t *m_sids;
2250 2259 int m_num;
2251 2260 int mids_size;
2252 2261 int i, rc;
2253 2262
2254 2263 grp->sg_nmembers = 0;
2255 2264 grp->sg_members = NULL;
2256 2265
2257 2266 m_num = atoi(nmembers);
2258 2267 mids_size = m_num * sizeof (smb_lgmid_t);
2259 2268 if ((m_ids = malloc(mids_size)) == NULL)
2260 2269 return (SMB_LGRP_NO_MEMORY);
2261 2270
2262 2271 m_sids = calloc(m_num, sizeof (smb_gsid_t));
2263 2272 if (m_sids == NULL) {
2264 2273 free(m_ids);
2265 2274 return (SMB_LGRP_NO_MEMORY);
2266 2275 }
2267 2276
2268 2277 (void) hextobin(members, strlen(members), (char *)m_ids, mids_size);
2269 2278
2270 2279 m_id = m_ids;
2271 2280 m_sid = m_sids;
2272 2281 for (i = 0; i < m_num; i++, m_id++, m_sid++) {
2273 2282 rc = smb_lgrp_getsid(m_id->m_idx, &m_id->m_rid, m_id->m_type,
2274 2283 db, &m_sid->gs_sid);
2275 2284
2276 2285 if (rc != SMB_LGRP_SUCCESS) {
2277 2286 free(m_ids);
2278 2287 for (m_sid = m_sids; m_sid->gs_sid != NULL; m_sid++)
2279 2288 smb_sid_free(m_sid->gs_sid);
2280 2289 free(m_sids);
2281 2290 return (rc);
2282 2291 }
2283 2292
2284 2293 m_sid->gs_type = m_id->m_type;
2285 2294 }
2286 2295
2287 2296 free(m_ids);
2288 2297
2289 2298 grp->sg_nmembers = m_num;
2290 2299 grp->sg_members = m_sids;
2291 2300 return (SMB_LGRP_SUCCESS);
2292 2301 }
2293 2302
2294 2303 /*
2295 2304 * smb_lgrp_decode
2296 2305 *
2297 2306 * Fills out the fields of the given group (grp) based in the
2298 2307 * string information read from the group table. infolvl determines
2299 2308 * which fields are requested and need to be decoded.
2300 2309 *
2301 2310 * Allocated memories must be freed by calling smb_lgrp_free()
2302 2311 * upon successful return.
2303 2312 */
2304 2313 static int
2305 2314 smb_lgrp_decode(smb_group_t *grp, char **values, int infolvl, sqlite *db)
2306 2315 {
2307 2316 uint32_t sid_idx;
2308 2317 int rc;
2309 2318
2310 2319 if (infolvl == SMB_LGRP_INFO_NONE)
2311 2320 return (SMB_LGRP_SUCCESS);
2312 2321
2313 2322 if (infolvl & SMB_LGRP_INFO_NAME) {
2314 2323 grp->sg_name = strdup(values[SMB_LGRP_GTBL_NAME]);
2315 2324 if (grp->sg_name == NULL)
2316 2325 return (SMB_LGRP_NO_MEMORY);
2317 2326 }
2318 2327
2319 2328 if (infolvl & SMB_LGRP_INFO_CMNT) {
2320 2329 grp->sg_cmnt = strdup(values[SMB_LGRP_GTBL_CMNT]);
2321 2330 if (grp->sg_cmnt == NULL) {
2322 2331 smb_lgrp_free(grp);
2323 2332 return (SMB_LGRP_NO_MEMORY);
2324 2333 }
2325 2334 }
2326 2335
2327 2336
2328 2337 if (infolvl & SMB_LGRP_INFO_SID) {
2329 2338 sid_idx = atoi(values[SMB_LGRP_GTBL_SIDIDX]);
2330 2339 grp->sg_rid = atoi(values[SMB_LGRP_GTBL_SIDRID]);
2331 2340 grp->sg_attr = atoi(values[SMB_LGRP_GTBL_SIDATR]);
2332 2341 grp->sg_id.gs_type = atoi(values[SMB_LGRP_GTBL_SIDTYP]);
2333 2342 rc = smb_lgrp_getsid(sid_idx, &grp->sg_rid, grp->sg_id.gs_type,
2334 2343 db, &grp->sg_id.gs_sid);
2335 2344 if (rc != SMB_LGRP_SUCCESS) {
2336 2345 smb_lgrp_free(grp);
2337 2346 return (rc);
2338 2347 }
2339 2348 grp->sg_domain = (sid_idx == SMB_LGRP_LOCAL_IDX)
2340 2349 ? SMB_DOMAIN_LOCAL : SMB_DOMAIN_BUILTIN;
2341 2350 }
2342 2351
2343 2352 if (infolvl & SMB_LGRP_INFO_PRIV) {
2344 2353 rc = smb_lgrp_decode_privset(grp, values[SMB_LGRP_GTBL_NPRIVS],
2345 2354 values[SMB_LGRP_GTBL_PRIVS]);
2346 2355
2347 2356 if (rc != SMB_LGRP_SUCCESS) {
2348 2357 smb_lgrp_free(grp);
2349 2358 return (rc);
2350 2359 }
2351 2360 }
2352 2361
2353 2362 if (infolvl & SMB_LGRP_INFO_MEMB) {
2354 2363 rc = smb_lgrp_decode_members(grp, values[SMB_LGRP_GTBL_NMEMBS],
2355 2364 values[SMB_LGRP_GTBL_MEMBS], db);
2356 2365 if (rc != SMB_LGRP_SUCCESS) {
2357 2366 smb_lgrp_free(grp);
2358 2367 return (rc);
2359 2368 }
2360 2369 }
2361 2370
2362 2371 return (SMB_LGRP_SUCCESS);
2363 2372 }
2364 2373
2365 2374 /*
2366 2375 * smb_lgrp_normalize_name
2367 2376 *
2368 2377 * Trim whitespace, validate the group name and convert it to lowercase.
2369 2378 */
2370 2379 static boolean_t
2371 2380 smb_lgrp_normalize_name(char *name)
2372 2381 {
2373 2382 (void) trim_whitespace(name);
2374 2383
2375 2384 if (smb_name_validate_account(name) != ERROR_SUCCESS)
2376 2385 return (B_FALSE);
2377 2386
2378 2387 (void) smb_strlwr(name);
2379 2388 return (B_TRUE);
2380 2389 }
2381 2390
2382 2391 /*
2383 2392 * smb_lgrp_set_default_privs
2384 2393 *
2385 2394 * set default privileges for Administrators and Backup Operators
2386 2395 */
2387 2396 static void
2388 2397 smb_lgrp_set_default_privs(smb_group_t *grp)
2389 2398 {
2390 2399 if (smb_strcasecmp(grp->sg_name, "Administrators", 0) == 0) {
2391 2400 smb_privset_enable(grp->sg_privs, SE_TAKE_OWNERSHIP_LUID);
2392 2401 return;
2393 2402 }
2394 2403
2395 2404 if (smb_strcasecmp(grp->sg_name, "Backup Operators", 0) == 0) {
2396 2405 smb_privset_enable(grp->sg_privs, SE_BACKUP_LUID);
2397 2406 smb_privset_enable(grp->sg_privs, SE_RESTORE_LUID);
2398 2407 return;
2399 2408 }
2400 2409 }
2401 2410
2402 2411 /*
2403 2412 * smb_lgrp_getsid
2404 2413 *
2405 2414 * Returns a SID based on the provided information
2406 2415 * If dom_idx is 0, it means 'rid' contains a UID/GID and the
2407 2416 * returned SID will be a local SID. If dom_idx is not 0 then
2408 2417 * the domain SID will be fetched from the domain table.
2409 2418 */
2410 2419 static int
2411 2420 smb_lgrp_getsid(int dom_idx, uint32_t *rid, uint16_t sid_type,
2412 2421 sqlite *db, smb_sid_t **sid)
2413 2422 {
2414 2423 smb_sid_t *dom_sid = NULL;
2415 2424 smb_sid_t *res_sid = NULL;
2416 2425 idmap_stat stat;
2417 2426 int id_type;
2418 2427 int rc;
2419 2428
2420 2429 *sid = NULL;
2421 2430 if (dom_idx == SMB_LGRP_LOCAL_IDX) {
2422 2431 id_type = (sid_type == SidTypeUser)
2423 2432 ? SMB_IDMAP_USER : SMB_IDMAP_GROUP;
2424 2433 stat = smb_idmap_getsid(*rid, id_type, &res_sid);
2425 2434 if (stat != IDMAP_SUCCESS) {
2426 2435 syslog(LOG_ERR, "smb_lgrp_getsid: "
2427 2436 "failed to get a SID for %s id=%u (%d)",
2428 2437 (id_type == SMB_IDMAP_USER) ? "user" : "group",
2429 2438 *rid, stat);
2430 2439 return (SMB_LGRP_NO_SID);
2431 2440 }
2432 2441
2433 2442 /*
2434 2443 * Make sure the returned SID is local
2435 2444 */
2436 2445 if (!smb_sid_indomain(smb_localgrp.lg_machine_sid, res_sid)) {
2437 2446 syslog(LOG_ERR, "smb_lgrp_getsid: "
2438 2447 "local %s (%u) is mapped to a non-local SID",
2439 2448 (id_type == SMB_IDMAP_USER) ? "user" : "group",
2440 2449 *rid);
2441 2450 smb_sid_free(res_sid);
2442 2451 return (SMB_LGRP_SID_NOTLOCAL);
2443 2452 }
2444 2453
2445 2454 (void) smb_sid_getrid(res_sid, rid);
2446 2455 *sid = res_sid;
2447 2456 return (SMB_LGRP_SUCCESS);
2448 2457 }
2449 2458
2450 2459 rc = smb_lgrp_dtbl_getsid(db, dom_idx, &dom_sid);
2451 2460 if (rc != SMB_LGRP_SUCCESS) {
2452 2461 syslog(LOG_ERR, "smb_lgrp_getsid: %s", smb_lgrp_strerror(rc));
2453 2462 return (SMB_LGRP_DB_ERROR);
2454 2463 }
2455 2464
2456 2465 res_sid = smb_sid_splice(dom_sid, *rid);
2457 2466 smb_sid_free(dom_sid);
2458 2467 if (res_sid == NULL) {
2459 2468 syslog(LOG_ERR, "smb_lgrp_getsid: %s", smb_lgrp_strerror(rc));
2460 2469 return (SMB_LGRP_NO_MEMORY);
2461 2470 }
2462 2471
2463 2472 *sid = res_sid;
2464 2473 return (SMB_LGRP_SUCCESS);
2465 2474 }
2466 2475
2467 2476 /*
2468 2477 * smb_lgrp_getgid
2469 2478 *
2470 2479 * Converts given local RID to a local gid since for user
2471 2480 * defined local groups, gid is stored in the table.
2472 2481 */
2473 2482 static int
2474 2483 smb_lgrp_getgid(uint32_t rid, gid_t *gid)
2475 2484 {
2476 2485 smb_sid_t *sid;
2477 2486 int idtype;
2478 2487 int rc;
2479 2488
2480 2489 if ((sid = smb_sid_splice(smb_localgrp.lg_machine_sid, rid)) == NULL)
2481 2490 return (SMB_LGRP_NO_MEMORY);
2482 2491
2483 2492 idtype = SMB_IDMAP_GROUP;
2484 2493 rc = smb_idmap_getid(sid, gid, &idtype);
2485 2494 smb_sid_free(sid);
2486 2495
2487 2496 return ((rc == IDMAP_SUCCESS) ? SMB_LGRP_SUCCESS : SMB_LGRP_NOT_FOUND);
2488 2497 }
2489 2498
2490 2499 /*
2491 2500 * smb_lgrp_exists
2492 2501 *
2493 2502 * Returns B_TRUE if the local group with the given name exists.
2494 2503 * Otherwise, returns B_FALSE.
2495 2504 */
2496 2505 static boolean_t
2497 2506 smb_lgrp_exists(char *gname)
2498 2507 {
2499 2508 sqlite *db;
2500 2509 boolean_t rc;
2501 2510
2502 2511 if (!smb_lgrp_normalize_name(gname))
2503 2512 return (B_FALSE);
2504 2513
2505 2514 db = smb_lgrp_db_open(SMB_LGRP_DB_ORD);
2506 2515 if (db == NULL)
2507 2516 return (B_FALSE);
2508 2517
2509 2518 rc = smb_lgrp_gtbl_exists(db, gname);
2510 2519 smb_lgrp_db_close(db);
2511 2520
2512 2521 return (rc);
2513 2522 }
2514 2523
2515 2524 /*
2516 2525 * smb_lgrp_pgrp_valid_gname
2517 2526 *
2518 2527 * Validate posix group name string.
2519 2528 */
2520 2529 static int
2521 2530 smb_lgrp_pgrp_valid_gname(char *group)
2522 2531 {
2523 2532 char *ptr = group;
2524 2533 char c;
2525 2534 int len = 0;
2526 2535 int badchar = 0;
2527 2536
2528 2537 if (!group || !*group)
2529 2538 return (SMB_LGRP_PGRP_INVALID);
2530 2539
2531 2540 for (c = *ptr; c != NULL; ptr++, c = *ptr) {
2532 2541 len++;
2533 2542 if (!isprint(c) || (c == ':') || (c == '\n'))
2534 2543 return (SMB_LGRP_PGRP_INVALID);
2535 2544
2536 2545 if (!(islower(c) || isdigit(c)))
2537 2546 badchar++;
2538 2547 }
2539 2548
2540 2549 if ((len > SMB_LGRP_PGRP_MAXGLEN - 1) || (badchar != 0))
2541 2550 return (SMB_LGRP_PGRP_INVALID);
2542 2551
2543 2552 if (getgrnam(group) != NULL)
2544 2553 return (SMB_LGRP_PGRP_NOTUNIQUE);
2545 2554
2546 2555 return (SMB_LGRP_PGRP_UNIQUE);
2547 2556 }
2548 2557
2549 2558 /*
2550 2559 * smb_lgrp_pgrp_add
2551 2560 *
2552 2561 * Create a posix group with the given name.
2553 2562 * This group will be added to the /etc/group file.
2554 2563 */
2555 2564 static int
2556 2565 smb_lgrp_pgrp_add(char *group)
2557 2566 {
2558 2567 FILE *etcgrp;
2559 2568 FILE *etctmp;
2560 2569 int o_mask;
2561 2570 int newdone = 0;
2562 2571 struct stat sb;
2563 2572 char buf[SMB_LGRP_PGRP_GRPBUFSIZ];
2564 2573 gid_t gid;
2565 2574 int rc = 0;
2566 2575
2567 2576 rc = smb_lgrp_pgrp_valid_gname(group);
2568 2577 if ((rc == SMB_LGRP_PGRP_INVALID) || (rc == SMB_LGRP_PGRP_NOTUNIQUE))
2569 2578 return (-1);
2570 2579
2571 2580 if ((findnextgid(SMB_LGRP_PGRP_DEFRID, MAXUID, &gid)) != 0)
2572 2581 return (-1);
2573 2582
2574 2583 if ((etcgrp = fopen(SMB_LGRP_PGRP_GROUP, "r")) == NULL)
2575 2584 return (-1);
2576 2585
2577 2586 if (fstat(fileno(etcgrp), &sb) < 0)
2578 2587 sb.st_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH;
2579 2588
2580 2589 o_mask = umask(077);
2581 2590 etctmp = fopen(SMB_LGRP_PGRP_GRPTMP, "w+");
2582 2591 (void) umask(o_mask);
2583 2592
2584 2593 if (etctmp == NULL) {
2585 2594 (void) fclose(etcgrp);
2586 2595 return (-1);
2587 2596 }
2588 2597
2589 2598 if (lockf(fileno(etctmp), F_LOCK, 0) != 0) {
2590 2599 (void) fclose(etcgrp);
2591 2600 (void) fclose(etctmp);
2592 2601 (void) unlink(SMB_LGRP_PGRP_GRPTMP);
2593 2602 return (-1);
2594 2603 }
2595 2604
2596 2605 if (fchmod(fileno(etctmp), sb.st_mode) != 0 ||
2597 2606 fchown(fileno(etctmp), sb.st_uid, sb.st_gid) != 0) {
2598 2607 (void) lockf(fileno(etctmp), F_ULOCK, 0);
2599 2608 (void) fclose(etcgrp);
2600 2609 (void) fclose(etctmp);
2601 2610 (void) unlink(SMB_LGRP_PGRP_GRPTMP);
2602 2611 return (-1);
2603 2612 }
2604 2613
2605 2614 while (fgets(buf, SMB_LGRP_PGRP_GRPBUFSIZ, etcgrp) != NULL) {
2606 2615 /* Check for NameService reference */
2607 2616 if (!newdone && (buf[0] == '+' || buf[0] == '-')) {
2608 2617 (void) fprintf(etctmp, "%s::%u:\n", group, gid);
2609 2618 newdone = 1;
2610 2619 }
2611 2620
2612 2621 (void) fputs(buf, etctmp);
2613 2622 }
2614 2623 (void) fclose(etcgrp);
2615 2624
2616 2625 if (!newdone)
2617 2626 (void) fprintf(etctmp, "%s::%u:\n", group, gid);
2618 2627
2619 2628 if (rename(SMB_LGRP_PGRP_GRPTMP, SMB_LGRP_PGRP_GROUP) < 0) {
2620 2629 (void) lockf(fileno(etctmp), F_ULOCK, 0);
2621 2630 (void) fclose(etctmp);
2622 2631 (void) unlink(SMB_LGRP_PGRP_GRPTMP);
2623 2632 return (-1);
2624 2633 }
2625 2634
2626 2635 (void) lockf(fileno(etctmp), F_ULOCK, 0);
2627 2636 (void) fclose(etctmp);
2628 2637 return (0);
2629 2638 }
|
↓ open down ↓ |
543 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX