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