4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
24 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
25 * Copyright (c) 2013 RackTop Systems.
37 #include <smbsrv/libsmb.h>
38 #include <smb_sqlite.h>
39 #include <sys/types.h>
41 #include <sys/param.h>
42 #include <libcmdutils.h>
45 * Local domain SID (aka machine SID) is not stored in the domain table
46 * therefore the index is 0
48 #define SMB_LGRP_LOCAL_IDX 0
49 #define SMB_LGRP_BUILTIN_IDX 1
51 #define SMB_LGRP_DB_NAME "/var/smb/smbgroup.db"
52 #define SMB_LGRP_DB_TIMEOUT 3000 /* in millisecond */
53 #define SMB_LGRP_DB_VERMAJOR 1
54 #define SMB_LGRP_DB_VERMINOR 0
55 #define SMB_LGRP_DB_MAGIC 0x4C475250 /* LGRP */
57 #define SMB_LGRP_DB_ORD 1 /* open read-only */
58 #define SMB_LGRP_DB_ORW 2 /* open read/write */
60 #define SMB_LGRP_DB_ADDMEMBER 1
61 #define SMB_LGRP_DB_DELMEMBER 2
64 * members column of the groups table is an array of
65 * member structure smb_lgmid_t defined below.
67 * privs column of the groups table is an array of bytes
68 * where each byte is the id of an enable privilege
70 #define SMB_LGRP_DB_SQL \
71 "CREATE TABLE db_info (" \
72 " ver_major INTEGER," \
73 " ver_minor INTEGER," \
77 "CREATE TABLE domains (" \
78 " dom_idx INTEGER PRIMARY KEY," \
79 " dom_sid TEXT UNIQUE," \
83 "CREATE UNIQUE INDEX domsid_idx ON domains (dom_sid);" \
85 "CREATE TABLE groups (" \
86 " name TEXT PRIMARY KEY," \
89 " sid_type INTEGER," \
90 " sid_attrs INTEGER," \
94 " n_members INTEGER," \
98 "CREATE INDEX grprid_idx ON groups (sid_rid);"
101 * Number of groups table columns
103 #define SMB_LGRP_GTBL_NCOL 10
105 #define SMB_LGRP_GTBL_NAME 0
106 #define SMB_LGRP_GTBL_SIDIDX 1
107 #define SMB_LGRP_GTBL_SIDRID 2
108 #define SMB_LGRP_GTBL_SIDTYP 3
109 #define SMB_LGRP_GTBL_SIDATR 4
110 #define SMB_LGRP_GTBL_CMNT 5
111 #define SMB_LGRP_GTBL_NPRIVS 6
112 #define SMB_LGRP_GTBL_PRIVS 7
113 #define SMB_LGRP_GTBL_NMEMBS 8
114 #define SMB_LGRP_GTBL_MEMBS 9
116 #define SMB_LGRP_INFO_NONE 0x00
117 #define SMB_LGRP_INFO_NAME 0x01
118 #define SMB_LGRP_INFO_CMNT 0x02
119 #define SMB_LGRP_INFO_SID 0x04
120 #define SMB_LGRP_INFO_PRIV 0x08
121 #define SMB_LGRP_INFO_MEMB 0x10
122 #define SMB_LGRP_INFO_ALL 0x1F
124 #define SMB_LGRP_PGRP_GRPTMP "/etc/gtmp"
125 #define SMB_LGRP_PGRP_GRPBUFSIZ 5120
126 #define SMB_LGRP_PGRP_GROUP "/etc/group"
127 #define SMB_LGRP_PGRP_MAXGLEN 9 /* max length of group name */
128 #define SMB_LGRP_PGRP_DEFRID 1000 /* lowest cifs created gid */
130 #define SMB_LGRP_PGRP_NOTUNIQUE 0
131 #define SMB_LGRP_PGRP_RESERVED 1
132 #define SMB_LGRP_PGRP_UNIQUE 2
133 #define SMB_LGRP_PGRP_TOOBIG 3
134 #define SMB_LGRP_PGRP_INVALID 4
136 #define NULL_MSGCHK(msg) ((msg) ? (msg) : "NULL")
139 typedef struct smb_lgmid
{
145 #define SMB_LGRP_MID_HEXSZ 32
148 typedef struct smb_lgmlist
{
154 typedef uint8_t smb_lgpid_t
;
157 typedef struct smb_lgplist
{
166 { SMB_LGRP_SUCCESS
, "success" },
167 { SMB_LGRP_INVALID_ARG
, "invalid argument" },
168 { SMB_LGRP_INVALID_MEMBER
, "invalid member type" },
169 { SMB_LGRP_INVALID_NAME
, "invalid name" },
170 { SMB_LGRP_NOT_FOUND
, "group not found" },
171 { SMB_LGRP_EXISTS
, "group exists" },
172 { SMB_LGRP_NO_SID
, "cannot obtain a SID" },
173 { SMB_LGRP_NO_LOCAL_SID
, "cannot get the machine SID" },
174 { SMB_LGRP_SID_NOTLOCAL
, "local account has non-local SID" },
176 "operation not permitted on well-known account" },
177 { SMB_LGRP_NO_MEMORY
, "not enough memory" },
178 { SMB_LGRP_DB_ERROR
, "database operation error" },
179 { SMB_LGRP_DBINIT_ERROR
, "database initialization error" },
180 { SMB_LGRP_INTERNAL_ERROR
, "internal error" },
181 { SMB_LGRP_MEMBER_IN_GROUP
, "member already in group" },
182 { SMB_LGRP_MEMBER_NOT_IN_GROUP
, "not a member" },
183 { SMB_LGRP_NO_SUCH_PRIV
, "no such privilege" },
184 { SMB_LGRP_NO_SUCH_DOMAIN
, "no such domain SID" },
185 { SMB_LGRP_PRIV_HELD
, "privilege already held" },
186 { SMB_LGRP_PRIV_NOT_HELD
, "privilege not held" },
187 { SMB_LGRP_BAD_DATA
, "bad data" },
188 { SMB_LGRP_NO_MORE
, "no more groups" },
189 { SMB_LGRP_DBOPEN_FAILED
, "database open failed" },
190 { SMB_LGRP_DBEXEC_FAILED
, "database operation failed" },
191 { SMB_LGRP_DBINIT_FAILED
, "database initialization failed" },
192 { SMB_LGRP_DOMLKP_FAILED
, "domain SID lookup failed" },
193 { SMB_LGRP_DOMINS_FAILED
, "domain SID insert failed" },
194 { SMB_LGRP_INSERT_FAILED
, "group insert failed" },
195 { SMB_LGRP_DELETE_FAILED
, "group delete failed" },
196 { SMB_LGRP_UPDATE_FAILED
, "group update failed" },
197 { SMB_LGRP_LOOKUP_FAILED
, "group lookup failed" },
198 { SMB_LGRP_OFFLINE
, "local group service is offline" },
199 { SMB_LGRP_POSIXCREATE_FAILED
, "posix group create failed" }
203 * Serialization for the local group API.
210 smb_sid_t
*lg_machine_sid
;
213 static smb_localgrp_t smb_localgrp
;
215 static boolean_t
smb_lgrp_enter(void);
216 static void smb_lgrp_exit(void);
217 static int smb_lgrp_db_init(void);
218 static sqlite
*smb_lgrp_db_open(int);
219 static void smb_lgrp_db_close(sqlite
*);
220 static int smb_lgrp_db_setinfo(sqlite
*);
222 static boolean_t
smb_lgrp_gtbl_exists(sqlite
*, char *);
223 static int smb_lgrp_gtbl_lookup(sqlite
*, int, smb_group_t
*, int, ...);
224 static int smb_lgrp_gtbl_insert(sqlite
*, smb_group_t
*);
225 static int smb_lgrp_gtbl_update(sqlite
*, char *, smb_group_t
*, int);
226 static int smb_lgrp_gtbl_delete(sqlite
*, char *);
227 static int smb_lgrp_gtbl_update_mlist(sqlite
*, char *, smb_gsid_t
*, int);
228 static int smb_lgrp_gtbl_update_plist(sqlite
*, char *, uint8_t, boolean_t
);
229 static int smb_lgrp_gtbl_count(sqlite
*, int, int *);
231 static int smb_lgrp_dtbl_insert(sqlite
*, char *, uint32_t *);
232 static int smb_lgrp_dtbl_getidx(sqlite
*, smb_sid_t
*, uint16_t,
233 uint32_t *, uint32_t *);
234 static int smb_lgrp_dtbl_getsid(sqlite
*, uint32_t, smb_sid_t
**);
236 static int smb_lgrp_mlist_add(smb_lgmlist_t
*, smb_lgmid_t
*, smb_lgmlist_t
*);
237 static int smb_lgrp_mlist_del(smb_lgmlist_t
*, smb_lgmid_t
*, smb_lgmlist_t
*);
239 static int smb_lgrp_plist_add(smb_lgplist_t
*, smb_lgpid_t
, smb_lgplist_t
*);
240 static int smb_lgrp_plist_del(smb_lgplist_t
*, smb_lgpid_t
, smb_lgplist_t
*);
242 static void smb_lgrp_encode_privset(smb_group_t
*, smb_lgplist_t
*);
244 static int smb_lgrp_decode(smb_group_t
*, char **, int, sqlite
*);
245 static int smb_lgrp_decode_privset(smb_group_t
*, char *, char *);
246 static int smb_lgrp_decode_members(smb_group_t
*, char *, char *, sqlite
*);
248 static void smb_lgrp_set_default_privs(smb_group_t
*);
249 static boolean_t
smb_lgrp_normalize_name(char *);
250 static boolean_t
smb_lgrp_chkmember(uint16_t);
251 static int smb_lgrp_getsid(int, uint32_t *, uint16_t, sqlite
*, smb_sid_t
**);
252 static int smb_lgrp_getgid(uint32_t rid
, gid_t
*gid
);
253 static boolean_t
smb_lgrp_exists(char *);
254 static int smb_lgrp_pgrp_add(char *);
259 * Create a local group with the given name and comment.
260 * This new group doesn't have any members and no enabled
263 * No well-known accounts can be added other than Administators,
264 * Backup Operators and Power Users. These built-in groups
265 * won't have any members when created but a set of default
266 * privileges will be enabled for them.
269 smb_lgrp_add(char *gname
, char *cmnt
)
274 smb_sid_t
*sid
= NULL
;
278 if (!smb_lgrp_normalize_name(gname
))
279 return (SMB_LGRP_INVALID_NAME
);
281 if (cmnt
&& (strlen(cmnt
) > SMB_LGRP_COMMENT_MAX
))
282 return (SMB_LGRP_INVALID_ARG
);
284 bzero(&grp
, sizeof (grp
));
285 grp
.sg_name
= smb_strlwr(gname
);
288 if (!smb_lgrp_enter())
289 return (SMB_LGRP_OFFLINE
);
291 wka
= smb_wka_lookup_name(gname
);
293 if ((pxgrp
= getgrnam(gname
)) == NULL
) {
294 if (smb_lgrp_pgrp_add(gname
) != 0) {
296 return (SMB_LGRP_POSIXCREATE_FAILED
);
299 if ((pxgrp
= getgrnam(gname
)) == NULL
) {
301 return (SMB_LGRP_NOT_FOUND
);
306 * Make sure a local SID can be obtained
308 if (smb_idmap_getsid(pxgrp
->gr_gid
, SMB_IDMAP_GROUP
, &sid
)
311 return (SMB_LGRP_NO_SID
);
314 if (!smb_sid_indomain(smb_localgrp
.lg_machine_sid
, sid
)) {
317 return (SMB_LGRP_SID_NOTLOCAL
);
321 grp
.sg_id
.gs_type
= SidTypeAlias
;
322 grp
.sg_domain
= SMB_DOMAIN_LOCAL
;
323 grp
.sg_rid
= pxgrp
->gr_gid
;
325 if ((wka
->wka_flags
& SMB_WKAFLG_LGRP_ENABLE
) == 0) {
326 /* cannot add well-known accounts */
328 return (SMB_LGRP_WKSID
);
331 grp
.sg_id
.gs_type
= wka
->wka_type
;
332 if ((sid
= smb_sid_fromstr(wka
->wka_sid
)) == NULL
) {
334 return (SMB_LGRP_NO_MEMORY
);
337 (void) smb_sid_getrid(sid
, &grp
.sg_rid
);
339 grp
.sg_domain
= SMB_DOMAIN_BUILTIN
;
340 grp
.sg_privs
= smb_privset_new();
341 smb_lgrp_set_default_privs(&grp
);
344 if (smb_lgrp_exists(grp
.sg_name
)) {
346 return (SMB_LGRP_EXISTS
);
349 grp
.sg_attr
= SE_GROUP_MANDATORY
| SE_GROUP_ENABLED_BY_DEFAULT
|
352 db
= smb_lgrp_db_open(SMB_LGRP_DB_ORW
);
353 rc
= smb_lgrp_gtbl_insert(db
, &grp
);
354 smb_lgrp_db_close(db
);
356 smb_privset_free(grp
.sg_privs
);
364 * Renames the given group
367 smb_lgrp_rename(char *gname
, char *new_gname
)
373 if (!smb_lgrp_normalize_name(gname
))
374 return (SMB_LGRP_INVALID_NAME
);
376 if (!smb_lgrp_normalize_name(gname
))
377 return (SMB_LGRP_INVALID_NAME
);
379 if (smb_strcasecmp(gname
, new_gname
, 0) == 0)
380 return (SMB_LGRP_SUCCESS
);
382 /* Cannot rename well-known groups */
383 if (smb_wka_lookup_name(gname
) != NULL
)
384 return (SMB_LGRP_WKSID
);
386 /* Cannot rename to a well-known groups */
387 if (smb_wka_lookup_name(new_gname
) != NULL
)
388 return (SMB_LGRP_WKSID
);
390 grp
.sg_name
= new_gname
;
392 if (!smb_lgrp_enter())
393 return (SMB_LGRP_OFFLINE
);
395 if (getgrnam(new_gname
) == NULL
) {
396 if (smb_lgrp_pgrp_add(new_gname
) != 0) {
398 return (SMB_LGRP_POSIXCREATE_FAILED
);
401 if (getgrnam(new_gname
) == NULL
) {
403 return (SMB_LGRP_NOT_FOUND
);
407 db
= smb_lgrp_db_open(SMB_LGRP_DB_ORW
);
408 rc
= smb_lgrp_gtbl_update(db
, gname
, &grp
, SMB_LGRP_GTBL_NAME
);
409 smb_lgrp_db_close(db
);
418 * Deletes the specified local group.
421 smb_lgrp_delete(char *gname
)
426 if (!smb_lgrp_normalize_name(gname
))
427 return (SMB_LGRP_INVALID_NAME
);
429 /* Cannot remove a built-in group */
430 if (smb_wka_lookup_name(gname
) != NULL
)
431 return (SMB_LGRP_WKSID
);
434 if (!smb_lgrp_exists(gname
))
435 return (SMB_LGRP_NOT_FOUND
);
437 if (!smb_lgrp_enter())
438 return (SMB_LGRP_OFFLINE
);
440 db
= smb_lgrp_db_open(SMB_LGRP_DB_ORW
);
441 rc
= smb_lgrp_gtbl_delete(db
, gname
);
442 smb_lgrp_db_close(db
);
451 * Sets the description for the given group
454 smb_lgrp_setcmnt(char *gname
, char *cmnt
)
460 if (!smb_lgrp_normalize_name(gname
))
461 return (SMB_LGRP_INVALID_NAME
);
463 if (cmnt
&& (strlen(cmnt
) > SMB_LGRP_COMMENT_MAX
))
464 return (SMB_LGRP_INVALID_ARG
);
468 if (!smb_lgrp_enter())
469 return (SMB_LGRP_OFFLINE
);
471 db
= smb_lgrp_db_open(SMB_LGRP_DB_ORW
);
472 rc
= smb_lgrp_gtbl_update(db
, gname
, &grp
, SMB_LGRP_GTBL_CMNT
);
473 smb_lgrp_db_close(db
);
482 * Obtain the description of the specified group
485 smb_lgrp_getcmnt(char *gname
, char **cmnt
)
491 if (!smb_lgrp_normalize_name(gname
))
492 return (SMB_LGRP_INVALID_NAME
);
495 return (SMB_LGRP_INVALID_ARG
);
497 if (!smb_lgrp_enter())
498 return (SMB_LGRP_OFFLINE
);
500 db
= smb_lgrp_db_open(SMB_LGRP_DB_ORD
);
501 rc
= smb_lgrp_gtbl_lookup(db
, SMB_LGRP_GTBL_NAME
, &grp
,
502 SMB_LGRP_INFO_CMNT
, gname
);
503 smb_lgrp_db_close(db
);
506 if (rc
== SMB_LGRP_SUCCESS
) {
519 * Enable/disable the specified privilge for the group
522 smb_lgrp_setpriv(char *gname
, uint8_t priv_lid
, boolean_t enable
)
527 if (!smb_lgrp_normalize_name(gname
))
528 return (SMB_LGRP_INVALID_NAME
);
530 if ((priv_lid
< SE_MIN_LUID
) || (priv_lid
> SE_MAX_LUID
))
531 return (SMB_LGRP_NO_SUCH_PRIV
);
533 if (!smb_lgrp_enter())
534 return (SMB_LGRP_OFFLINE
);
536 db
= smb_lgrp_db_open(SMB_LGRP_DB_ORW
);
537 rc
= smb_lgrp_gtbl_update_plist(db
, gname
, priv_lid
, enable
);
538 smb_lgrp_db_close(db
);
542 if (rc
== SMB_LGRP_PRIV_HELD
)
543 rc
= SMB_LGRP_SUCCESS
;
545 if (rc
== SMB_LGRP_PRIV_NOT_HELD
)
546 rc
= SMB_LGRP_SUCCESS
;
555 * Obtain the status of the specified privilge for the group
558 smb_lgrp_getpriv(char *gname
, uint8_t priv_lid
, boolean_t
*enable
)
564 if (!smb_lgrp_normalize_name(gname
))
565 return (SMB_LGRP_INVALID_NAME
);
567 if ((priv_lid
< SE_MIN_LUID
) || (priv_lid
> SE_MAX_LUID
))
568 return (SMB_LGRP_NO_SUCH_PRIV
);
570 if (!smb_lgrp_enter())
571 return (SMB_LGRP_OFFLINE
);
573 db
= smb_lgrp_db_open(SMB_LGRP_DB_ORD
);
574 rc
= smb_lgrp_gtbl_lookup(db
, SMB_LGRP_GTBL_NAME
, &grp
,
575 SMB_LGRP_INFO_PRIV
, gname
);
576 smb_lgrp_db_close(db
);
579 if (rc
== SMB_LGRP_SUCCESS
) {
580 *enable
= (smb_privset_query(grp
.sg_privs
, priv_lid
) == 1);
588 * smb_lgrp_add_member
590 * Add the given account to the specified group as its member.
593 smb_lgrp_add_member(char *gname
, smb_sid_t
*msid
, uint16_t sid_type
)
599 if (!smb_lgrp_normalize_name(gname
))
600 return (SMB_LGRP_INVALID_NAME
);
602 if (!smb_sid_isvalid(msid
))
603 return (SMB_LGRP_INVALID_ARG
);
605 if (!smb_lgrp_chkmember(sid_type
))
606 return (SMB_LGRP_INVALID_MEMBER
);
609 mid
.gs_type
= sid_type
;
611 if (!smb_lgrp_enter())
612 return (SMB_LGRP_OFFLINE
);
614 db
= smb_lgrp_db_open(SMB_LGRP_DB_ORW
);
615 rc
= smb_lgrp_gtbl_update_mlist(db
, gname
, &mid
, SMB_LGRP_DB_ADDMEMBER
);
616 smb_lgrp_db_close(db
);
623 * smb_lgrp_del_member
625 * Delete the specified member from the given group.
628 smb_lgrp_del_member(char *gname
, smb_sid_t
*msid
, uint16_t sid_type
)
634 if (!smb_lgrp_normalize_name(gname
))
635 return (SMB_LGRP_INVALID_NAME
);
637 if (!smb_sid_isvalid(msid
))
638 return (SMB_LGRP_INVALID_ARG
);
641 mid
.gs_type
= sid_type
;
643 if (!smb_lgrp_enter())
644 return (SMB_LGRP_OFFLINE
);
646 db
= smb_lgrp_db_open(SMB_LGRP_DB_ORW
);
647 rc
= smb_lgrp_gtbl_update_mlist(db
, gname
, &mid
, SMB_LGRP_DB_DELMEMBER
);
648 smb_lgrp_db_close(db
);
657 * Retrieves the information of the group specified by
660 * Note that this function doesn't allocate the group
661 * structure itself only the fields, so the given grp
662 * pointer has to point to a group structure.
663 * Caller must free the allocated memories for the fields
664 * by calling smb_lgrp_free().
667 smb_lgrp_getbyname(char *gname
, smb_group_t
*grp
)
672 if (!smb_lgrp_normalize_name(gname
))
673 return (SMB_LGRP_INVALID_NAME
);
675 if (!smb_lgrp_enter())
676 return (SMB_LGRP_OFFLINE
);
678 db
= smb_lgrp_db_open(SMB_LGRP_DB_ORD
);
679 rc
= smb_lgrp_gtbl_lookup(db
, SMB_LGRP_GTBL_NAME
, grp
,
680 SMB_LGRP_INFO_ALL
, gname
);
681 smb_lgrp_db_close(db
);
690 * Retrieves the information of the group specified by
691 * the given RID and domain type.
693 * Note that this function doesn't allocate the group
694 * structure itself only the fields, so the given grp
695 * pointer has to point to a group structure.
696 * Caller must free the allocated memories for the fields
697 * by calling smb_lgrp_free().
699 * If grp is NULL no information would be returned. The
700 * return value of SMB_LGRP_SUCCESS will indicate that a
701 * group with the given information exists.
704 smb_lgrp_getbyrid(uint32_t rid
, smb_domain_type_t domtype
, smb_group_t
*grp
)
708 int infolvl
= SMB_LGRP_INFO_ALL
;
711 if (!smb_lgrp_enter())
712 return (SMB_LGRP_OFFLINE
);
716 infolvl
= SMB_LGRP_INFO_NONE
;
719 db
= smb_lgrp_db_open(SMB_LGRP_DB_ORD
);
720 rc
= smb_lgrp_gtbl_lookup(db
, SMB_LGRP_GTBL_SIDRID
, grp
, infolvl
,
722 smb_lgrp_db_close(db
);
729 * smb_lgrp_numbydomain
731 * Returns the number of groups in the given domain in the
735 smb_lgrp_numbydomain(smb_domain_type_t dom_type
, int *count
)
742 case SMB_DOMAIN_LOCAL
:
743 dom_idx
= SMB_LGRP_LOCAL_IDX
;
745 case SMB_DOMAIN_BUILTIN
:
746 dom_idx
= SMB_LGRP_BUILTIN_IDX
;
750 return (SMB_LGRP_INVALID_ARG
);
753 if (!smb_lgrp_enter())
754 return (SMB_LGRP_OFFLINE
);
756 db
= smb_lgrp_db_open(SMB_LGRP_DB_ORD
);
757 rc
= smb_lgrp_gtbl_count(db
, dom_idx
, count
);
758 smb_lgrp_db_close(db
);
767 * Frees the allocated memory for the fields of the given
768 * group structure. Note that this function doesn't free
772 smb_lgrp_free(smb_group_t
*grp
)
781 smb_sid_free(grp
->sg_id
.gs_sid
);
782 smb_privset_free(grp
->sg_privs
);
784 for (i
= 0; i
< grp
->sg_nmembers
; i
++)
785 smb_sid_free(grp
->sg_members
[i
].gs_sid
);
786 free(grp
->sg_members
);
792 * Initializes the given group iterator by opening
793 * the group database and creating a virtual machine
797 smb_lgrp_iteropen(smb_giter_t
*iter
)
801 int rc
= SMB_LGRP_SUCCESS
;
805 if (!smb_lgrp_enter())
806 return (SMB_LGRP_OFFLINE
);
808 bzero(iter
, sizeof (smb_giter_t
));
810 sql
= sqlite_mprintf("SELECT * FROM groups");
813 return (SMB_LGRP_NO_MEMORY
);
816 iter
->sgi_db
= smb_lgrp_db_open(SMB_LGRP_DB_ORD
);
817 if (iter
->sgi_db
== NULL
) {
820 return (SMB_LGRP_DBOPEN_FAILED
);
823 rc
= sqlite_compile(iter
->sgi_db
, sql
, NULL
, &iter
->sgi_vm
, &errmsg
);
826 if (rc
!= SQLITE_OK
) {
827 syslog(LOG_DEBUG
, "failed to create a VM (%s)",
828 NULL_MSGCHK(errmsg
));
829 rc
= SMB_LGRP_DB_ERROR
;
839 * Closes the given group iterator.
842 smb_lgrp_iterclose(smb_giter_t
*iter
)
849 if (!smb_lgrp_enter())
852 rc
= sqlite_finalize(iter
->sgi_vm
, &errmsg
);
853 if (rc
!= SQLITE_OK
) {
854 syslog(LOG_DEBUG
, "failed to destroy a VM (%s)",
855 NULL_MSGCHK(errmsg
));
858 smb_lgrp_db_close(iter
->sgi_db
);
863 * Returns B_TRUE if there has been an error during
867 smb_lgrp_itererror(smb_giter_t
*iter
)
869 return (iter
->sgi_nerr
!= 0);
875 * Iterate through group database
876 * Group information is returned in provided group structure.
878 * Note that this function doesn't allocate the group
879 * structure itself only the fields, so the given grp
880 * pointer has to point to a group structure.
881 * Caller must free the allocated memories for the fields
882 * by calling smb_lgrp_free().
885 smb_lgrp_iterate(smb_giter_t
*iter
, smb_group_t
*grp
)
892 if (iter
->sgi_vm
== NULL
|| iter
->sgi_db
== NULL
)
893 return (SMB_LGRP_INVALID_ARG
);
895 if (!smb_lgrp_enter())
896 return (SMB_LGRP_OFFLINE
);
899 bzero(grp
, sizeof (smb_group_t
));
900 rc
= sqlite_step(iter
->sgi_vm
, &ncol
, &values
, NULL
);
901 if (rc
== SQLITE_DONE
) {
903 return (SMB_LGRP_NO_MORE
);
906 if (rc
!= SQLITE_ROW
) {
908 return (SMB_LGRP_DBEXEC_FAILED
);
911 if (ncol
!= SMB_LGRP_GTBL_NCOL
) {
913 return (SMB_LGRP_DB_ERROR
);
916 for (i
= 0; i
< ncol
; i
++) {
917 if (values
[i
] == NULL
) {
919 return (SMB_LGRP_DB_ERROR
);
923 rc
= smb_lgrp_decode(grp
, (char **)values
, SMB_LGRP_INFO_ALL
,
925 if (rc
== SMB_LGRP_SUCCESS
)
929 syslog(LOG_ERR
, "smb_lgrp_iterate: %s", smb_lgrp_strerror(rc
));
940 * Check to see if the specified account is a member of
944 smb_lgrp_is_member(smb_group_t
*grp
, smb_sid_t
*sid
)
948 if (grp
== NULL
|| grp
->sg_members
== NULL
|| sid
== NULL
)
951 for (i
= 0; i
< grp
->sg_nmembers
; i
++) {
952 if (smb_sid_cmp(grp
->sg_members
[i
].gs_sid
, sid
))
962 * Returns a text for the given group error code.
965 smb_lgrp_strerror(int errnum
)
968 int nerr
= (sizeof (errtab
) / sizeof (errtab
[0]));
970 for (i
= 0; i
< nerr
; ++i
) {
971 if (errnum
== errtab
[i
].errnum
)
972 return (errtab
[i
].errmsg
);
975 return ("unknown local group error");
979 * smb_lgrp_err_to_ntstatus
981 * This routine maps Local group operation errors to NT Status error codes.
984 smb_lgrp_err_to_ntstatus(uint32_t lgrp_err
)
987 static struct err_map
{
991 { SMB_LGRP_SUCCESS
, NT_STATUS_SUCCESS
},
992 { SMB_LGRP_INVALID_ARG
, NT_STATUS_INVALID_PARAMETER
},
993 { SMB_LGRP_INVALID_MEMBER
, NT_STATUS_INVALID_MEMBER
},
994 { SMB_LGRP_INVALID_NAME
, NT_STATUS_INVALID_PARAMETER
},
995 { SMB_LGRP_NOT_FOUND
, NT_STATUS_NO_SUCH_ALIAS
},
996 { SMB_LGRP_EXISTS
, NT_STATUS_ALIAS_EXISTS
},
997 { SMB_LGRP_NO_SID
, NT_STATUS_INVALID_SID
},
998 { SMB_LGRP_NO_LOCAL_SID
, NT_STATUS_INVALID_SID
},
999 { SMB_LGRP_SID_NOTLOCAL
, NT_STATUS_INVALID_SID
},
1000 { SMB_LGRP_WKSID
, NT_STATUS_INVALID_SID
},
1001 { SMB_LGRP_NO_MEMORY
, NT_STATUS_NO_MEMORY
},
1002 { SMB_LGRP_DB_ERROR
, NT_STATUS_INTERNAL_DB_ERROR
},
1003 { SMB_LGRP_DBINIT_ERROR
, NT_STATUS_INTERNAL_DB_ERROR
},
1004 { SMB_LGRP_INTERNAL_ERROR
, NT_STATUS_INTERNAL_ERROR
},
1005 { SMB_LGRP_MEMBER_IN_GROUP
, NT_STATUS_MEMBER_IN_ALIAS
},
1006 { SMB_LGRP_MEMBER_NOT_IN_GROUP
, NT_STATUS_MEMBER_NOT_IN_ALIAS
},
1007 { SMB_LGRP_NO_SUCH_PRIV
, NT_STATUS_NO_SUCH_PRIVILEGE
},
1008 { SMB_LGRP_NO_SUCH_DOMAIN
, NT_STATUS_NO_SUCH_DOMAIN
},
1009 { SMB_LGRP_PRIV_HELD
, NT_STATUS_SUCCESS
},
1010 { SMB_LGRP_PRIV_NOT_HELD
, NT_STATUS_PRIVILEGE_NOT_HELD
},
1011 { SMB_LGRP_BAD_DATA
, NT_STATUS_DATA_ERROR
},
1012 { SMB_LGRP_NO_MORE
, NT_STATUS_NO_MORE_ENTRIES
},
1013 { SMB_LGRP_DBOPEN_FAILED
, NT_STATUS_INTERNAL_DB_ERROR
},
1014 { SMB_LGRP_DBEXEC_FAILED
, NT_STATUS_INTERNAL_DB_ERROR
},
1015 { SMB_LGRP_DBINIT_FAILED
, NT_STATUS_INTERNAL_DB_ERROR
},
1016 { SMB_LGRP_DOMLKP_FAILED
, NT_STATUS_INTERNAL_DB_ERROR
},
1017 { SMB_LGRP_DOMINS_FAILED
, NT_STATUS_INTERNAL_DB_ERROR
},
1018 { SMB_LGRP_INSERT_FAILED
, NT_STATUS_INTERNAL_DB_ERROR
},
1019 { SMB_LGRP_DELETE_FAILED
, NT_STATUS_INTERNAL_DB_ERROR
},
1020 { SMB_LGRP_UPDATE_FAILED
, NT_STATUS_INTERNAL_DB_ERROR
},
1021 { SMB_LGRP_LOOKUP_FAILED
, NT_STATUS_INTERNAL_DB_ERROR
},
1022 { SMB_LGRP_NOT_SUPPORTED
, NT_STATUS_NOT_SUPPORTED
},
1023 { SMB_LGRP_OFFLINE
, NT_STATUS_INTERNAL_ERROR
},
1024 { SMB_LGRP_POSIXCREATE_FAILED
, NT_STATUS_UNSUCCESSFUL
}
1027 for (i
= 0; i
< sizeof (err_map
)/sizeof (err_map
[0]); ++i
) {
1028 if (err_map
[i
].lgrp_err
== lgrp_err
)
1029 return (err_map
[i
].nt_status
);
1032 return (NT_STATUS_INTERNAL_ERROR
);
1036 * smb_lgrp_chkmember
1038 * Determines valid account types for being member of
1039 * a local group. We really have no business trying to
1040 * keep track of the "type" of SIDs in a group, so just
1041 * validate that the SID type is a known enum value.
1044 smb_lgrp_chkmember(uint16_t sid_type
)
1051 case SidTypeWellKnownGroup
:
1052 case SidTypeDeletedAccount
:
1053 case SidTypeInvalid
:
1054 case SidTypeUnknown
:
1063 * Initializes the library private global variables.
1064 * Create the database, if it doesn't exist, and add
1065 * the predefined builtin groups.
1068 smb_lgrp_start(void)
1070 static char *builtin
[] = {
1078 int ngrp
= sizeof (builtin
) / sizeof (builtin
[0]);
1080 (void) mutex_lock(&smb_localgrp
.lg_mutex
);
1082 if ((localsid
= smb_config_get_localsid()) == NULL
) {
1083 (void) mutex_unlock(&smb_localgrp
.lg_mutex
);
1084 return (SMB_LGRP_NO_LOCAL_SID
);
1087 smb_localgrp
.lg_machine_sid
= smb_sid_fromstr(localsid
);
1090 if (!smb_sid_isvalid(smb_localgrp
.lg_machine_sid
)) {
1091 free(smb_localgrp
.lg_machine_sid
);
1092 smb_localgrp
.lg_machine_sid
= NULL
;
1093 (void) mutex_unlock(&smb_localgrp
.lg_mutex
);
1094 return (SMB_LGRP_NO_LOCAL_SID
);
1097 rc
= smb_lgrp_db_init();
1098 if (rc
!= SMB_LGRP_SUCCESS
) {
1099 free(smb_localgrp
.lg_machine_sid
);
1100 smb_localgrp
.lg_machine_sid
= NULL
;
1101 (void) mutex_unlock(&smb_localgrp
.lg_mutex
);
1105 smb_localgrp
.lg_online
= B_TRUE
;
1106 (void) mutex_unlock(&smb_localgrp
.lg_mutex
);
1108 for (i
= 0; i
< ngrp
; i
++) {
1111 if ((wka
= smb_wka_lookup_name(builtin
[i
])) == NULL
)
1114 if ((tname
= strdup(wka
->wka_name
)) == NULL
)
1115 return (SMB_LGRP_NO_MEMORY
);
1116 if (!smb_lgrp_exists(tname
)) {
1117 rc
= smb_lgrp_add(tname
, wka
->wka_desc
);
1118 if (rc
!= SMB_LGRP_SUCCESS
) {
1119 syslog(LOG_DEBUG
, "failed to add %s",
1126 return (SMB_LGRP_SUCCESS
);
1132 * Unintialize the library global private variables.
1137 (void) mutex_lock(&smb_localgrp
.lg_mutex
);
1138 if (!smb_localgrp
.lg_online
)
1141 smb_localgrp
.lg_online
= B_FALSE
;
1143 while (smb_localgrp
.lg_refcnt
> 0)
1144 (void) cond_wait(&smb_localgrp
.lg_cv
, &smb_localgrp
.lg_mutex
);
1146 free(smb_localgrp
.lg_machine_sid
);
1147 smb_localgrp
.lg_machine_sid
= NULL
;
1148 (void) mutex_unlock(&smb_localgrp
.lg_mutex
);
1152 smb_lgrp_enter(void)
1156 (void) mutex_lock(&smb_localgrp
.lg_mutex
);
1158 status
= smb_localgrp
.lg_online
;
1160 if (smb_localgrp
.lg_online
)
1161 ++smb_localgrp
.lg_refcnt
;
1163 (void) mutex_unlock(&smb_localgrp
.lg_mutex
);
1170 (void) mutex_lock(&smb_localgrp
.lg_mutex
);
1171 assert(smb_localgrp
.lg_refcnt
> 0);
1173 if ((--smb_localgrp
.lg_refcnt
) == 0)
1174 (void) cond_signal(&smb_localgrp
.lg_cv
);
1176 (void) mutex_unlock(&smb_localgrp
.lg_mutex
);
1182 * Opens group database with the given mode.
1185 smb_lgrp_db_open(int mode
)
1188 char *errmsg
= NULL
;
1190 db
= sqlite_open(SMB_LGRP_DB_NAME
, mode
, &errmsg
);
1192 syslog(LOG_ERR
, "failed to open group database (%s)",
1193 NULL_MSGCHK(errmsg
));
1194 sqlite_freemem(errmsg
);
1203 * Closes the given database handle
1206 smb_lgrp_db_close(sqlite
*db
)
1216 * Creates the group database based on the defined SQL statement.
1217 * It also initializes db_info and domain tables.
1220 smb_lgrp_db_init(void)
1222 int dbrc
= SQLITE_OK
;
1223 int rc
= SMB_LGRP_SUCCESS
;
1225 char *errmsg
= NULL
;
1227 db
= sqlite_open(SMB_LGRP_DB_NAME
, 0600, &errmsg
);
1229 syslog(LOG_ERR
, "failed to create group database (%s)",
1230 NULL_MSGCHK(errmsg
));
1231 sqlite_freemem(errmsg
);
1232 return (SMB_LGRP_DBOPEN_FAILED
);
1235 sqlite_busy_timeout(db
, SMB_LGRP_DB_TIMEOUT
);
1236 dbrc
= sqlite_exec(db
, "BEGIN TRANSACTION;", NULL
, NULL
, &errmsg
);
1237 if (dbrc
!= SQLITE_OK
) {
1238 syslog(LOG_DEBUG
, "failed to begin database transaction (%s)",
1239 NULL_MSGCHK(errmsg
));
1240 sqlite_freemem(errmsg
);
1242 return (SMB_LGRP_DBEXEC_FAILED
);
1245 switch (sqlite_exec(db
, SMB_LGRP_DB_SQL
, NULL
, NULL
, &errmsg
)) {
1248 * This is the normal situation: CREATE probably failed because
1249 * tables already exist. It may indicate an error in SQL as well
1250 * but we cannot tell.
1252 sqlite_freemem(errmsg
);
1253 dbrc
= sqlite_exec(db
, "ROLLBACK TRANSACTION", NULL
, NULL
,
1255 rc
= SMB_LGRP_SUCCESS
;
1259 dbrc
= sqlite_exec(db
, "COMMIT TRANSACTION", NULL
, NULL
,
1261 if (dbrc
!= SQLITE_OK
)
1263 rc
= smb_lgrp_dtbl_insert(db
, NT_BUILTIN_DOMAIN_SIDSTR
,
1265 if (rc
== SMB_LGRP_SUCCESS
)
1266 rc
= smb_lgrp_db_setinfo(db
);
1267 if (rc
!= SMB_LGRP_SUCCESS
) {
1268 (void) sqlite_close(db
);
1269 (void) unlink(SMB_LGRP_DB_NAME
);
1276 "failed to initialize group database (%s)", errmsg
);
1277 sqlite_freemem(errmsg
);
1278 dbrc
= sqlite_exec(db
, "ROLLBACK TRANSACTION", NULL
, NULL
,
1280 rc
= SMB_LGRP_DBINIT_FAILED
;
1284 if (dbrc
!= SQLITE_OK
) {
1285 /* this is bad - database may be left in a locked state */
1286 syslog(LOG_DEBUG
, "failed to close a transaction (%s)",
1287 NULL_MSGCHK(errmsg
));
1288 sqlite_freemem(errmsg
);
1291 (void) sqlite_close(db
);
1296 * smb_lgrp_gtbl_lookup
1298 * This is a flexible lookup function for the group database.
1299 * The key type can be specified by the 'key' arg and the actual key
1300 * values can be passed after the 'infolvl' arg. 'infolvl' arg specifies
1301 * what information items for the specified group is needed.
1303 * Note that the function assumes the given key is unique and only
1304 * specifies one or 0 group. The keys that are supported now are
1305 * the group name and the group SID
1307 * Note that this function doesn't allocate the group
1308 * structure itself only the fields, so the given grp
1309 * pointer has to point to a group structure.
1310 * Caller must free the allocated memories for the fields
1311 * by calling smb_lgrp_free().
1314 smb_lgrp_gtbl_lookup(sqlite
*db
, int key
, smb_group_t
*grp
, int infolvl
, ...)
1316 char *errmsg
= NULL
;
1325 return (SMB_LGRP_DBOPEN_FAILED
);
1327 bzero(grp
, sizeof (smb_group_t
));
1328 va_start(ap
, infolvl
);
1331 case SMB_LGRP_GTBL_NAME
:
1332 grpkey
.sg_name
= va_arg(ap
, char *);
1333 sql
= sqlite_mprintf("SELECT * FROM groups WHERE name = '%s'",
1337 case SMB_LGRP_GTBL_SIDRID
:
1338 grpkey
.sg_rid
= va_arg(ap
, uint32_t);
1339 grpkey
.sg_domain
= va_arg(ap
, smb_domain_type_t
);
1340 if (grpkey
.sg_domain
== SMB_DOMAIN_LOCAL
) {
1341 dom_idx
= SMB_LGRP_LOCAL_IDX
;
1342 /* need to map the given rid to a gid */
1343 rc
= smb_lgrp_getgid(grpkey
.sg_rid
,
1344 (gid_t
*)&grpkey
.sg_rid
);
1345 if (rc
!= SMB_LGRP_SUCCESS
) {
1350 dom_idx
= SMB_LGRP_BUILTIN_IDX
;
1353 sql
= sqlite_mprintf("SELECT * FROM groups "
1354 "WHERE (sid_idx = %d) AND (sid_rid = %u)",
1355 dom_idx
, grpkey
.sg_rid
);
1360 return (SMB_LGRP_INVALID_ARG
);
1365 return (SMB_LGRP_NO_MEMORY
);
1367 rc
= sqlite_get_table(db
, sql
, &result
, &nrow
, &ncol
, &errmsg
);
1368 sqlite_freemem(sql
);
1370 if (rc
!= SQLITE_OK
) {
1371 syslog(LOG_DEBUG
, "failed to lookup (%s)", NULL_MSGCHK(errmsg
));
1372 sqlite_freemem(errmsg
);
1373 return (SMB_LGRP_LOOKUP_FAILED
);
1377 /* group not found */
1378 sqlite_free_table(result
);
1379 return (SMB_LGRP_NOT_FOUND
);
1382 if (nrow
!= 1 || ncol
!= SMB_LGRP_GTBL_NCOL
) {
1383 sqlite_free_table(result
);
1384 return (SMB_LGRP_DB_ERROR
);
1387 rc
= smb_lgrp_decode(grp
, &result
[SMB_LGRP_GTBL_NCOL
], infolvl
, db
);
1388 sqlite_free_table(result
);
1393 * smb_lgrp_gtbl_exists
1395 * Checks to see if the given group exists or not.
1398 smb_lgrp_gtbl_exists(sqlite
*db
, char *gname
)
1400 char *errmsg
= NULL
;
1409 sql
= sqlite_mprintf("SELECT name FROM groups WHERE name = '%s'",
1411 rc
= sqlite_get_table(db
, sql
, &result
, &nrow
, &ncol
, &errmsg
);
1412 sqlite_freemem(sql
);
1414 if (rc
!= SQLITE_OK
) {
1415 syslog(LOG_DEBUG
, "failed to lookup %s (%s)",
1416 gname
, NULL_MSGCHK(errmsg
));
1417 sqlite_freemem(errmsg
);
1421 sqlite_free_table(result
);
1426 * smb_lgrp_gtbl_count
1428 * Counts the number of groups in the domain specified by
1432 smb_lgrp_gtbl_count(sqlite
*db
, int dom_idx
, int *count
)
1434 char *errmsg
= NULL
;
1442 return (SMB_LGRP_DBOPEN_FAILED
);
1444 sql
= sqlite_mprintf("SELECT sid_idx FROM groups WHERE sid_idx = %d",
1446 rc
= sqlite_get_table(db
, sql
, &result
, &nrow
, &ncol
, &errmsg
);
1447 sqlite_freemem(sql
);
1449 if (rc
!= SQLITE_OK
) {
1450 syslog(LOG_DEBUG
, "failed to count (%s)", NULL_MSGCHK(errmsg
));
1451 sqlite_freemem(errmsg
);
1452 return (SMB_LGRP_LOOKUP_FAILED
);
1455 sqlite_free_table(result
);
1457 return (SMB_LGRP_DB_ERROR
);
1460 return (SMB_LGRP_SUCCESS
);
1464 * smb_lgrp_gtbl_insert
1466 * Insert a record for the given group in the group database.
1468 * NOTE: this function assumes that this group has no members
1472 smb_lgrp_gtbl_insert(sqlite
*db
, smb_group_t
*grp
)
1474 smb_lgpid_t privs
[SE_MAX_LUID
+ 1];
1475 smb_lgplist_t plist
;
1476 char *errmsg
= NULL
;
1482 return (SMB_LGRP_DBOPEN_FAILED
);
1484 dom_idx
= (grp
->sg_domain
== SMB_DOMAIN_LOCAL
)
1485 ? SMB_LGRP_LOCAL_IDX
: SMB_LGRP_BUILTIN_IDX
;
1487 plist
.p_cnt
= SE_MAX_LUID
;
1488 plist
.p_ids
= privs
;
1489 smb_lgrp_encode_privset(grp
, &plist
);
1491 sql
= sqlite_mprintf("INSERT INTO groups "
1492 "(name, sid_idx, sid_rid, sid_type, sid_attrs, comment, "
1493 "n_privs, privs, n_members, members) "
1494 "VALUES('%s', %u, %u, %u, %u, '%q', %u, '%q', %u, '%q')",
1495 grp
->sg_name
, dom_idx
, grp
->sg_rid
, grp
->sg_id
.gs_type
,
1496 grp
->sg_attr
, (grp
->sg_cmnt
) ? grp
->sg_cmnt
: "",
1497 plist
.p_cnt
, (char *)plist
.p_ids
, 0, "");
1500 return (SMB_LGRP_NO_MEMORY
);
1502 rc
= sqlite_exec(db
, sql
, NULL
, NULL
, &errmsg
);
1503 sqlite_freemem(sql
);
1505 if (rc
!= SQLITE_OK
) {
1506 syslog(LOG_DEBUG
, "failed to insert %s (%s)",
1507 grp
->sg_name
, NULL_MSGCHK(errmsg
));
1508 sqlite_freemem(errmsg
);
1509 rc
= SMB_LGRP_INSERT_FAILED
;
1511 rc
= SMB_LGRP_SUCCESS
;
1518 * smb_lgrp_gtbl_delete
1520 * Removes the specified group from the database
1523 smb_lgrp_gtbl_delete(sqlite
*db
, char *gname
)
1525 char *errmsg
= NULL
;
1530 return (SMB_LGRP_DBOPEN_FAILED
);
1532 sql
= sqlite_mprintf("DELETE FROM groups WHERE name = '%s'", gname
);
1534 return (SMB_LGRP_NO_MEMORY
);
1536 rc
= sqlite_exec(db
, sql
, NULL
, NULL
, &errmsg
);
1537 sqlite_freemem(sql
);
1539 if (rc
!= SQLITE_OK
) {
1540 syslog(LOG_DEBUG
, "failed to delete %s (%s)",
1541 gname
, NULL_MSGCHK(errmsg
));
1542 sqlite_freemem(errmsg
);
1543 rc
= SMB_LGRP_DELETE_FAILED
;
1545 rc
= SMB_LGRP_SUCCESS
;
1552 * smb_lgrp_gtbl_update
1554 * Updates the specified group information, the supported items
1555 * are group name and comment
1558 smb_lgrp_gtbl_update(sqlite
*db
, char *gname
, smb_group_t
*grp
, int col_id
)
1560 char *errmsg
= NULL
;
1565 return (SMB_LGRP_DBOPEN_FAILED
);
1567 /* UPDATE doesn't fail if gname doesn't exist */
1568 if (!smb_lgrp_gtbl_exists(db
, gname
))
1569 return (SMB_LGRP_NOT_FOUND
);
1572 case SMB_LGRP_GTBL_NAME
:
1573 if (smb_lgrp_gtbl_exists(db
, grp
->sg_name
))
1574 return (SMB_LGRP_EXISTS
);
1575 sql
= sqlite_mprintf("UPDATE groups SET name = '%s' "
1576 "WHERE name = '%s'", grp
->sg_name
, gname
);
1579 case SMB_LGRP_GTBL_CMNT
:
1580 sql
= sqlite_mprintf("UPDATE groups SET comment = '%q' "
1581 "WHERE name = '%s'", grp
->sg_cmnt
, gname
);
1585 return (SMB_LGRP_INVALID_ARG
);
1589 return (SMB_LGRP_NO_MEMORY
);
1591 rc
= sqlite_exec(db
, sql
, NULL
, NULL
, &errmsg
);
1592 sqlite_freemem(sql
);
1594 if (rc
!= SQLITE_OK
) {
1595 syslog(LOG_DEBUG
, "failed to update %s (%s)",
1596 gname
, NULL_MSGCHK(errmsg
));
1597 sqlite_freemem(errmsg
);
1598 rc
= SMB_LGRP_UPDATE_FAILED
;
1600 rc
= SMB_LGRP_SUCCESS
;
1607 * smb_lgrp_gtbl_update_mlist
1609 * Adds/removes the specified member from the member list of the
1613 smb_lgrp_gtbl_update_mlist(sqlite
*db
, char *gname
, smb_gsid_t
*member
,
1616 smb_lgmlist_t new_members
;
1617 smb_lgmlist_t members
;
1619 char *errmsg
= NULL
;
1626 return (SMB_LGRP_DBOPEN_FAILED
);
1628 sql
= sqlite_mprintf("SELECT n_members, members FROM groups "
1629 "WHERE name = '%s'", gname
);
1632 return (SMB_LGRP_NO_MEMORY
);
1634 rc
= sqlite_get_table(db
, sql
, &result
, &nrow
, &ncol
, &errmsg
);
1635 sqlite_freemem(sql
);
1637 if (rc
!= SQLITE_OK
) {
1638 syslog(LOG_DEBUG
, "failed to lookup %s (%s)",
1639 gname
, NULL_MSGCHK(errmsg
));
1640 sqlite_freemem(errmsg
);
1641 return (SMB_LGRP_LOOKUP_FAILED
);
1645 /* group not found */
1646 sqlite_free_table(result
);
1647 return (SMB_LGRP_NOT_FOUND
);
1650 if (nrow
!= 1 || ncol
!= 2) {
1651 sqlite_free_table(result
);
1652 return (SMB_LGRP_DB_ERROR
);
1655 bzero(&mid
, sizeof (mid
));
1656 mid
.m_type
= member
->gs_type
;
1657 rc
= smb_lgrp_dtbl_getidx(db
, member
->gs_sid
, mid
.m_type
,
1658 &mid
.m_idx
, &mid
.m_rid
);
1659 if (rc
!= SMB_LGRP_SUCCESS
) {
1660 sqlite_free_table(result
);
1664 members
.m_cnt
= atoi(result
[2]);
1665 members
.m_ids
= result
[3];
1668 case SMB_LGRP_DB_ADDMEMBER
:
1669 rc
= smb_lgrp_mlist_add(&members
, &mid
, &new_members
);
1671 case SMB_LGRP_DB_DELMEMBER
:
1672 rc
= smb_lgrp_mlist_del(&members
, &mid
, &new_members
);
1675 rc
= SMB_LGRP_INVALID_ARG
;
1678 sqlite_free_table(result
);
1679 if (rc
!= SMB_LGRP_SUCCESS
)
1682 sql
= sqlite_mprintf("UPDATE groups SET n_members = %u, members = '%s'"
1683 " WHERE name = '%s'", new_members
.m_cnt
, new_members
.m_ids
, gname
);
1685 free(new_members
.m_ids
);
1688 return (SMB_LGRP_NO_MEMORY
);
1690 rc
= sqlite_exec(db
, sql
, NULL
, NULL
, &errmsg
);
1691 sqlite_freemem(sql
);
1693 if (rc
!= SQLITE_OK
) {
1694 syslog(LOG_DEBUG
, "failed to update %s (%s)", gname
,
1695 NULL_MSGCHK(errmsg
));
1696 sqlite_freemem(errmsg
);
1697 rc
= SMB_LGRP_UPDATE_FAILED
;
1699 rc
= SMB_LGRP_SUCCESS
;
1706 * smb_lgrp_gtbl_update_plist
1708 * Adds/removes the specified privilege from the privilege list of the
1712 smb_lgrp_gtbl_update_plist(sqlite
*db
, char *gname
, uint8_t priv_id
,
1716 char *errmsg
= NULL
;
1720 smb_lgplist_t privs
;
1721 smb_lgplist_t new_privs
;
1724 return (SMB_LGRP_DBOPEN_FAILED
);
1726 sql
= sqlite_mprintf("SELECT n_privs, privs FROM groups "
1727 "WHERE name = '%s'", gname
);
1730 return (SMB_LGRP_NO_MEMORY
);
1732 rc
= sqlite_get_table(db
, sql
, &result
, &nrow
, &ncol
, &errmsg
);
1733 sqlite_freemem(sql
);
1735 if (rc
!= SQLITE_OK
) {
1736 syslog(LOG_DEBUG
, "failed to lookup %s (%s)",
1737 gname
, NULL_MSGCHK(errmsg
));
1738 sqlite_freemem(errmsg
);
1739 return (SMB_LGRP_LOOKUP_FAILED
);
1743 /* group not found */
1744 sqlite_free_table(result
);
1745 return (SMB_LGRP_NOT_FOUND
);
1748 if (nrow
!= 1 || ncol
!= 2) {
1749 sqlite_free_table(result
);
1750 return (SMB_LGRP_DB_ERROR
);
1753 privs
.p_cnt
= atoi(result
[2]);
1754 privs
.p_ids
= (smb_lgpid_t
*)result
[3];
1757 rc
= smb_lgrp_plist_add(&privs
, priv_id
, &new_privs
);
1759 rc
= smb_lgrp_plist_del(&privs
, priv_id
, &new_privs
);
1761 sqlite_free_table(result
);
1762 if (rc
!= SMB_LGRP_SUCCESS
)
1765 sql
= sqlite_mprintf("UPDATE groups SET n_privs = %u, privs = '%q'"
1766 " WHERE name = '%s'", new_privs
.p_cnt
, (char *)new_privs
.p_ids
,
1769 free(new_privs
.p_ids
);
1772 return (SMB_LGRP_NO_MEMORY
);
1774 rc
= sqlite_exec(db
, sql
, NULL
, NULL
, &errmsg
);
1775 sqlite_freemem(sql
);
1777 if (rc
!= SQLITE_OK
) {
1778 syslog(LOG_DEBUG
, "failed to update %s (%s)",
1779 gname
, NULL_MSGCHK(errmsg
));
1780 sqlite_freemem(errmsg
);
1781 rc
= SMB_LGRP_UPDATE_FAILED
;
1783 rc
= SMB_LGRP_SUCCESS
;
1790 * smb_lgrp_dtbl_insert
1792 * Inserts the specified domain SID in the dmain table.
1793 * Upon successful insert the index will be returned in
1797 smb_lgrp_dtbl_insert(sqlite
*db
, char *dom_sid
, uint32_t *dom_idx
)
1799 char *errmsg
= NULL
;
1803 sql
= sqlite_mprintf("INSERT INTO domains (dom_sid, dom_cnt)"
1804 " VALUES('%s', 1);", dom_sid
);
1806 return (SMB_LGRP_NO_MEMORY
);
1808 rc
= sqlite_exec(db
, sql
, NULL
, NULL
, &errmsg
);
1809 sqlite_freemem(sql
);
1811 if (rc
!= SQLITE_OK
) {
1812 syslog(LOG_DEBUG
, "failed to insert domain SID (%s)",
1813 NULL_MSGCHK(errmsg
));
1814 sqlite_freemem(errmsg
);
1815 return (SMB_LGRP_DOMINS_FAILED
);
1819 *dom_idx
= sqlite_last_insert_rowid(db
);
1820 return (SMB_LGRP_SUCCESS
);
1824 * smb_lgrp_dtbl_getidx
1826 * Searches the domain table for the domain SID of the
1827 * given member SID. If it finds the domain SID it'll
1828 * return the index and the RID, otherwise it'll insert
1829 * it in the domain table as a new SID.
1832 smb_lgrp_dtbl_getidx(sqlite
*db
, smb_sid_t
*sid
, uint16_t sid_type
,
1833 uint32_t *dom_idx
, uint32_t *rid
)
1835 char sidstr
[SMB_SID_STRSZ
];
1839 char *errmsg
= NULL
;
1843 if (smb_sid_indomain(smb_localgrp
.lg_machine_sid
, sid
)) {
1844 /* This is a local SID */
1845 int id_type
= (sid_type
== SidTypeUser
)
1846 ? SMB_IDMAP_USER
: SMB_IDMAP_GROUP
;
1847 *dom_idx
= SMB_LGRP_LOCAL_IDX
;
1848 if (smb_idmap_getid(sid
, rid
, &id_type
) != IDMAP_SUCCESS
)
1849 return (SMB_LGRP_INTERNAL_ERROR
);
1851 return (SMB_LGRP_SUCCESS
);
1854 if ((dom_sid
= smb_sid_split(sid
, rid
)) == NULL
)
1855 return (SMB_LGRP_NO_MEMORY
);
1857 smb_sid_tostr(dom_sid
, sidstr
);
1860 sql
= sqlite_mprintf("SELECT dom_idx FROM domains WHERE dom_sid = '%s'",
1863 return (SMB_LGRP_NO_MEMORY
);
1865 rc
= sqlite_get_table(db
, sql
, &result
, &nrow
, &ncol
, &errmsg
);
1866 sqlite_freemem(sql
);
1868 if (rc
!= SQLITE_OK
) {
1869 syslog(LOG_DEBUG
, "failed to lookup domain SID (%s)",
1870 NULL_MSGCHK(errmsg
));
1871 sqlite_freemem(errmsg
);
1872 return (SMB_LGRP_DOMLKP_FAILED
);
1877 /* new domain SID; insert it into the domains table */
1878 sqlite_free_table(result
);
1879 return (smb_lgrp_dtbl_insert(db
, sidstr
, dom_idx
));
1882 *dom_idx
= atoi(result
[1]);
1883 sqlite_free_table(result
);
1884 return (SMB_LGRP_SUCCESS
);
1887 sqlite_free_table(result
);
1888 return (SMB_LGRP_DB_ERROR
);
1892 * smb_lgrp_dtbl_getsid
1894 * Searchs the domain table for the given domain index.
1895 * Converts the found domain SID to binary format and
1896 * returns it in the 'sid' arg.
1898 * Caller must free the returned SID by calling free().
1901 smb_lgrp_dtbl_getsid(sqlite
*db
, uint32_t dom_idx
, smb_sid_t
**sid
)
1905 char *errmsg
= NULL
;
1909 sql
= sqlite_mprintf("SELECT dom_sid FROM domains WHERE dom_idx = %u",
1912 return (SMB_LGRP_NO_MEMORY
);
1914 rc
= sqlite_get_table(db
, sql
, &result
, &nrow
, &ncol
, &errmsg
);
1915 sqlite_freemem(sql
);
1917 if (rc
!= SQLITE_OK
) {
1918 syslog(LOG_DEBUG
, "failed to lookup domain index (%s)",
1919 NULL_MSGCHK(errmsg
));
1920 sqlite_freemem(errmsg
);
1921 return (SMB_LGRP_DOMLKP_FAILED
);
1926 rc
= SMB_LGRP_NO_SUCH_DOMAIN
;
1930 *sid
= smb_sid_fromstr(result
[1]);
1932 ? SMB_LGRP_INTERNAL_ERROR
: SMB_LGRP_SUCCESS
;
1936 rc
= SMB_LGRP_DB_ERROR
;
1940 sqlite_free_table(result
);
1945 * smb_lgrp_db_setinfo
1947 * Initializes the db_info table upon database creation.
1950 smb_lgrp_db_setinfo(sqlite
*db
)
1952 char *errmsg
= NULL
;
1956 sql
= sqlite_mprintf("INSERT INTO db_info (ver_major, ver_minor,"
1957 " magic) VALUES (%d, %d, %u)", SMB_LGRP_DB_VERMAJOR
,
1958 SMB_LGRP_DB_VERMINOR
, SMB_LGRP_DB_MAGIC
);
1961 return (SMB_LGRP_NO_MEMORY
);
1963 rc
= sqlite_exec(db
, sql
, NULL
, NULL
, &errmsg
);
1964 sqlite_freemem(sql
);
1965 if (rc
!= SQLITE_OK
) {
1966 syslog(LOG_DEBUG
, "failed to insert database information (%s)",
1967 NULL_MSGCHK(errmsg
));
1968 sqlite_freemem(errmsg
);
1969 rc
= SMB_LGRP_DBINIT_ERROR
;
1971 rc
= SMB_LGRP_SUCCESS
;
1978 * smb_lgrp_mlist_add
1980 * Adds the given member (newm) to the input member list (in_members)
1981 * if it's not already there. The result list will be returned in
1982 * out_members. The caller must free the allocated memory for
1983 * out_members by calling free().
1985 * in_members and out_members are hex strings.
1988 smb_lgrp_mlist_add(smb_lgmlist_t
*in_members
, smb_lgmid_t
*newm
,
1989 smb_lgmlist_t
*out_members
)
1991 char mid_hex
[SMB_LGRP_MID_HEXSZ
];
1999 out_members
->m_cnt
= 0;
2000 out_members
->m_ids
= NULL
;
2002 bzero(mid_hex
, sizeof (mid_hex
));
2003 mid_hexsz
= bintohex((const char *)newm
, sizeof (smb_lgmid_t
),
2004 mid_hex
, sizeof (mid_hex
));
2007 * Check to see if this is already a group member
2009 in_list
= in_members
->m_ids
;
2010 for (i
= 0; i
< in_members
->m_cnt
; i
++) {
2011 if (strncmp(in_list
, mid_hex
, mid_hexsz
) == 0)
2012 return (SMB_LGRP_MEMBER_IN_GROUP
);
2013 in_list
+= mid_hexsz
;
2016 in_size
= (in_members
->m_ids
) ? strlen(in_members
->m_ids
) : 0;
2017 out_size
= in_size
+ sizeof (mid_hex
) + 1;
2018 out_list
= malloc(out_size
);
2019 if (out_list
== NULL
)
2020 return (SMB_LGRP_NO_MEMORY
);
2022 bzero(out_list
, out_size
);
2023 if (in_members
->m_ids
)
2024 (void) strlcpy(out_list
, in_members
->m_ids
, out_size
);
2025 (void) strcat(out_list
, mid_hex
);
2027 out_members
->m_cnt
= in_members
->m_cnt
+ 1;
2028 out_members
->m_ids
= out_list
;
2030 return (SMB_LGRP_SUCCESS
);
2034 * smb_lgrp_mlist_del
2036 * Removes the given member (msid) from the input member list
2037 * (in_members) if it's already there. The result list will b
2038 * returned in out_members. The caller must free the allocated
2039 * memory for out_members by calling free().
2041 * in_members and out_members are hex strings.
2044 smb_lgrp_mlist_del(smb_lgmlist_t
*in_members
, smb_lgmid_t
*mid
,
2045 smb_lgmlist_t
*out_members
)
2047 char mid_hex
[SMB_LGRP_MID_HEXSZ
];
2056 out_members
->m_cnt
= 0;
2057 out_members
->m_ids
= NULL
;
2059 if ((in_members
== NULL
) || (in_members
->m_cnt
== 0))
2060 return (SMB_LGRP_MEMBER_NOT_IN_GROUP
);
2062 in_size
= strlen(in_members
->m_ids
);
2063 out_size
= in_size
+ sizeof (mid_hex
) + 1;
2064 out_list
= malloc(out_size
);
2065 if (out_list
== NULL
)
2066 return (SMB_LGRP_NO_MEMORY
);
2070 bzero(mid_hex
, sizeof (mid_hex
));
2071 mid_hexsz
= bintohex((const char *)mid
, sizeof (smb_lgmid_t
),
2072 mid_hex
, sizeof (mid_hex
));
2074 in_list
= in_members
->m_ids
;
2075 for (i
= 0, out_cnt
= 0; i
< in_members
->m_cnt
; i
++) {
2076 if (strncmp(in_list
, mid_hex
, mid_hexsz
)) {
2077 (void) strncat(out_list
, in_list
, mid_hexsz
);
2080 in_list
+= mid_hexsz
;
2083 if (out_cnt
== in_members
->m_cnt
) {
2085 return (SMB_LGRP_MEMBER_NOT_IN_GROUP
);
2088 out_members
->m_cnt
= out_cnt
;
2089 out_members
->m_ids
= out_list
;
2090 return (SMB_LGRP_SUCCESS
);
2094 * smb_lgrp_plist_add
2096 * Adds the given privilege to the input list (in_privs)
2097 * if it's not already there. The result list is returned
2098 * in out_privs. The caller must free the allocated memory
2099 * for out_privs by calling free().
2102 smb_lgrp_plist_add(smb_lgplist_t
*in_privs
, smb_lgpid_t priv_id
,
2103 smb_lgplist_t
*out_privs
)
2108 out_privs
->p_cnt
= 0;
2109 out_privs
->p_ids
= NULL
;
2111 for (i
= 0; i
< in_privs
->p_cnt
; i
++) {
2112 if (in_privs
->p_ids
[i
] == priv_id
)
2113 return (SMB_LGRP_PRIV_HELD
);
2116 size
= (in_privs
->p_cnt
+ 1) * sizeof (smb_lgpid_t
) + 1;
2117 pbuf
= malloc(size
);
2119 return (SMB_LGRP_NO_MEMORY
);
2122 bcopy(in_privs
->p_ids
, pbuf
, in_privs
->p_cnt
* sizeof (smb_lgpid_t
));
2123 pbuf
[in_privs
->p_cnt
] = priv_id
;
2125 out_privs
->p_cnt
= in_privs
->p_cnt
+ 1;
2126 out_privs
->p_ids
= pbuf
;
2128 return (SMB_LGRP_SUCCESS
);
2132 * smb_lgrp_plist_del
2134 * Removes the given privilege from the input list (in_privs)
2135 * if it's already there. The result list is returned
2136 * in out_privs. The caller must free the allocated memory
2137 * for out_privs by calling free().
2140 smb_lgrp_plist_del(smb_lgplist_t
*in_privs
, smb_lgpid_t priv_id
,
2141 smb_lgplist_t
*out_privs
)
2145 out_privs
->p_cnt
= 0;
2146 out_privs
->p_ids
= NULL
;
2148 if ((in_privs
== NULL
) || (in_privs
->p_cnt
== 0))
2149 return (SMB_LGRP_PRIV_NOT_HELD
);
2151 size
= (in_privs
->p_cnt
- 1) * sizeof (smb_lgpid_t
) + 1;
2152 out_privs
->p_ids
= malloc(size
);
2153 if (out_privs
->p_ids
== NULL
)
2154 return (SMB_LGRP_NO_MEMORY
);
2156 bzero(out_privs
->p_ids
, size
);
2158 for (i
= 0; i
< in_privs
->p_cnt
; i
++) {
2159 if (in_privs
->p_ids
[i
] != priv_id
)
2160 out_privs
->p_ids
[out_privs
->p_cnt
++] =
2164 if (out_privs
->p_cnt
== in_privs
->p_cnt
) {
2165 free(out_privs
->p_ids
);
2166 out_privs
->p_cnt
= 0;
2167 out_privs
->p_ids
= NULL
;
2168 return (SMB_LGRP_PRIV_NOT_HELD
);
2171 return (SMB_LGRP_SUCCESS
);
2175 * smb_lgrp_encode_privset
2177 * Encodes given privilege set into a buffer to be stored in the group
2178 * database. Each entry of the encoded buffer contains the privilege ID
2179 * of an enable privilege. The returned buffer is null-terminated.
2182 smb_lgrp_encode_privset(smb_group_t
*grp
, smb_lgplist_t
*plist
)
2184 smb_privset_t
*privs
;
2185 uint32_t pcnt
= plist
->p_cnt
;
2188 bzero(plist
->p_ids
, sizeof (smb_lgpid_t
) * plist
->p_cnt
);
2191 privs
= grp
->sg_privs
;
2192 if ((privs
== NULL
) || (privs
->priv_cnt
== 0))
2195 if (pcnt
< privs
->priv_cnt
) {
2199 for (i
= 0; i
< privs
->priv_cnt
; i
++) {
2200 if (privs
->priv
[i
].attrs
== SE_PRIVILEGE_ENABLED
) {
2201 plist
->p_ids
[plist
->p_cnt
++] =
2202 (uint8_t)privs
->priv
[i
].luid
.lo_part
;
2208 * smb_lgrp_decode_privset
2210 * Decodes the privilege information read from group table
2211 * (nprivs, privs) into a binray format specified by the
2212 * privilege field of smb_group_t
2215 smb_lgrp_decode_privset(smb_group_t
*grp
, char *nprivs
, char *privs
)
2217 smb_lgplist_t plist
;
2220 plist
.p_cnt
= atoi(nprivs
);
2221 if (strlen(privs
) != plist
.p_cnt
)
2222 return (SMB_LGRP_BAD_DATA
);
2224 plist
.p_ids
= (smb_lgpid_t
*)privs
;
2225 grp
->sg_privs
= smb_privset_new();
2226 if (grp
->sg_privs
== NULL
)
2227 return (SMB_LGRP_NO_MEMORY
);
2229 for (i
= 0; i
< plist
.p_cnt
; i
++)
2230 smb_privset_enable(grp
->sg_privs
, plist
.p_ids
[i
]);
2232 return (SMB_LGRP_SUCCESS
);
2236 * smb_lgrp_decode_members
2238 * Decodes the members information read from group table
2239 * (nmembers, members) into a binary format specified by the
2240 * member fields of smb_group_t
2243 smb_lgrp_decode_members(smb_group_t
*grp
, char *nmembers
, char *members
,
2254 grp
->sg_nmembers
= 0;
2255 grp
->sg_members
= NULL
;
2257 m_num
= atoi(nmembers
);
2258 mids_size
= m_num
* sizeof (smb_lgmid_t
);
2259 if ((m_ids
= malloc(mids_size
)) == NULL
)
2260 return (SMB_LGRP_NO_MEMORY
);
2262 m_sids
= calloc(m_num
, sizeof (smb_gsid_t
));
2263 if (m_sids
== NULL
) {
2265 return (SMB_LGRP_NO_MEMORY
);
2268 (void) hextobin(members
, strlen(members
), (char *)m_ids
, mids_size
);
2272 for (i
= 0; i
< m_num
; i
++, m_id
++, m_sid
++) {
2273 rc
= smb_lgrp_getsid(m_id
->m_idx
, &m_id
->m_rid
, m_id
->m_type
,
2274 db
, &m_sid
->gs_sid
);
2276 if (rc
!= SMB_LGRP_SUCCESS
) {
2278 for (m_sid
= m_sids
; m_sid
->gs_sid
!= NULL
; m_sid
++)
2279 smb_sid_free(m_sid
->gs_sid
);
2284 m_sid
->gs_type
= m_id
->m_type
;
2289 grp
->sg_nmembers
= m_num
;
2290 grp
->sg_members
= m_sids
;
2291 return (SMB_LGRP_SUCCESS
);
2297 * Fills out the fields of the given group (grp) based in the
2298 * string information read from the group table. infolvl determines
2299 * which fields are requested and need to be decoded.
2301 * Allocated memories must be freed by calling smb_lgrp_free()
2302 * upon successful return.
2305 smb_lgrp_decode(smb_group_t
*grp
, char **values
, int infolvl
, sqlite
*db
)
2310 if (infolvl
== SMB_LGRP_INFO_NONE
)
2311 return (SMB_LGRP_SUCCESS
);
2313 if (infolvl
& SMB_LGRP_INFO_NAME
) {
2314 grp
->sg_name
= strdup(values
[SMB_LGRP_GTBL_NAME
]);
2315 if (grp
->sg_name
== NULL
)
2316 return (SMB_LGRP_NO_MEMORY
);
2319 if (infolvl
& SMB_LGRP_INFO_CMNT
) {
2320 grp
->sg_cmnt
= strdup(values
[SMB_LGRP_GTBL_CMNT
]);
2321 if (grp
->sg_cmnt
== NULL
) {
2323 return (SMB_LGRP_NO_MEMORY
);
2328 if (infolvl
& SMB_LGRP_INFO_SID
) {
2329 sid_idx
= atoi(values
[SMB_LGRP_GTBL_SIDIDX
]);
2330 grp
->sg_rid
= atoi(values
[SMB_LGRP_GTBL_SIDRID
]);
2331 grp
->sg_attr
= atoi(values
[SMB_LGRP_GTBL_SIDATR
]);
2332 grp
->sg_id
.gs_type
= atoi(values
[SMB_LGRP_GTBL_SIDTYP
]);
2333 rc
= smb_lgrp_getsid(sid_idx
, &grp
->sg_rid
, grp
->sg_id
.gs_type
,
2334 db
, &grp
->sg_id
.gs_sid
);
2335 if (rc
!= SMB_LGRP_SUCCESS
) {
2339 grp
->sg_domain
= (sid_idx
== SMB_LGRP_LOCAL_IDX
)
2340 ? SMB_DOMAIN_LOCAL
: SMB_DOMAIN_BUILTIN
;
2343 if (infolvl
& SMB_LGRP_INFO_PRIV
) {
2344 rc
= smb_lgrp_decode_privset(grp
, values
[SMB_LGRP_GTBL_NPRIVS
],
2345 values
[SMB_LGRP_GTBL_PRIVS
]);
2347 if (rc
!= SMB_LGRP_SUCCESS
) {
2353 if (infolvl
& SMB_LGRP_INFO_MEMB
) {
2354 rc
= smb_lgrp_decode_members(grp
, values
[SMB_LGRP_GTBL_NMEMBS
],
2355 values
[SMB_LGRP_GTBL_MEMBS
], db
);
2356 if (rc
!= SMB_LGRP_SUCCESS
) {
2362 return (SMB_LGRP_SUCCESS
);
2366 * smb_lgrp_normalize_name
2368 * Trim whitespace, validate the group name and convert it to lowercase.
2371 smb_lgrp_normalize_name(char *name
)
2373 (void) trim_whitespace(name
);
2375 if (smb_name_validate_account(name
) != ERROR_SUCCESS
)
2378 (void) smb_strlwr(name
);
2383 * smb_lgrp_set_default_privs
2385 * set default privileges for Administrators and Backup Operators
2388 smb_lgrp_set_default_privs(smb_group_t
*grp
)
2390 if (smb_strcasecmp(grp
->sg_name
, "Administrators", 0) == 0) {
2391 smb_privset_enable(grp
->sg_privs
, SE_TAKE_OWNERSHIP_LUID
);
2395 if (smb_strcasecmp(grp
->sg_name
, "Backup Operators", 0) == 0) {
2396 smb_privset_enable(grp
->sg_privs
, SE_BACKUP_LUID
);
2397 smb_privset_enable(grp
->sg_privs
, SE_RESTORE_LUID
);
2405 * Returns a SID based on the provided information
2406 * If dom_idx is 0, it means 'rid' contains a UID/GID and the
2407 * returned SID will be a local SID. If dom_idx is not 0 then
2408 * the domain SID will be fetched from the domain table.
2411 smb_lgrp_getsid(int dom_idx
, uint32_t *rid
, uint16_t sid_type
,
2412 sqlite
*db
, smb_sid_t
**sid
)
2414 smb_sid_t
*dom_sid
= NULL
;
2415 smb_sid_t
*res_sid
= NULL
;
2421 if (dom_idx
== SMB_LGRP_LOCAL_IDX
) {
2422 id_type
= (sid_type
== SidTypeUser
)
2423 ? SMB_IDMAP_USER
: SMB_IDMAP_GROUP
;
2424 stat
= smb_idmap_getsid(*rid
, id_type
, &res_sid
);
2425 if (stat
!= IDMAP_SUCCESS
) {
2426 syslog(LOG_ERR
, "smb_lgrp_getsid: "
2427 "failed to get a SID for %s id=%u (%d)",
2428 (id_type
== SMB_IDMAP_USER
) ? "user" : "group",
2430 return (SMB_LGRP_NO_SID
);
2434 * Make sure the returned SID is local
2436 if (!smb_sid_indomain(smb_localgrp
.lg_machine_sid
, res_sid
)) {
2437 syslog(LOG_ERR
, "smb_lgrp_getsid: "
2438 "local %s (%u) is mapped to a non-local SID",
2439 (id_type
== SMB_IDMAP_USER
) ? "user" : "group",
2441 smb_sid_free(res_sid
);
2442 return (SMB_LGRP_SID_NOTLOCAL
);
2445 (void) smb_sid_getrid(res_sid
, rid
);
2447 return (SMB_LGRP_SUCCESS
);
2450 rc
= smb_lgrp_dtbl_getsid(db
, dom_idx
, &dom_sid
);
2451 if (rc
!= SMB_LGRP_SUCCESS
) {
2452 syslog(LOG_ERR
, "smb_lgrp_getsid: %s", smb_lgrp_strerror(rc
));
2453 return (SMB_LGRP_DB_ERROR
);
2456 res_sid
= smb_sid_splice(dom_sid
, *rid
);
2457 smb_sid_free(dom_sid
);
2458 if (res_sid
== NULL
) {
2459 syslog(LOG_ERR
, "smb_lgrp_getsid: %s", smb_lgrp_strerror(rc
));
2460 return (SMB_LGRP_NO_MEMORY
);
2464 return (SMB_LGRP_SUCCESS
);
2470 * Converts given local RID to a local gid since for user
2471 * defined local groups, gid is stored in the table.
2474 smb_lgrp_getgid(uint32_t rid
, gid_t
*gid
)
2480 if ((sid
= smb_sid_splice(smb_localgrp
.lg_machine_sid
, rid
)) == NULL
)
2481 return (SMB_LGRP_NO_MEMORY
);
2483 idtype
= SMB_IDMAP_GROUP
;
2484 rc
= smb_idmap_getid(sid
, gid
, &idtype
);
2487 return ((rc
== IDMAP_SUCCESS
) ? SMB_LGRP_SUCCESS
: SMB_LGRP_NOT_FOUND
);
2493 * Returns B_TRUE if the local group with the given name exists.
2494 * Otherwise, returns B_FALSE.
2497 smb_lgrp_exists(char *gname
)
2502 if (!smb_lgrp_normalize_name(gname
))
2505 db
= smb_lgrp_db_open(SMB_LGRP_DB_ORD
);
2509 rc
= smb_lgrp_gtbl_exists(db
, gname
);
2510 smb_lgrp_db_close(db
);
2516 * smb_lgrp_pgrp_valid_gname
2518 * Validate posix group name string.
2521 smb_lgrp_pgrp_valid_gname(char *group
)
2528 if (!group
|| !*group
)
2529 return (SMB_LGRP_PGRP_INVALID
);
2531 for (c
= *ptr
; c
!= NULL
; ptr
++, c
= *ptr
) {
2533 if (!isprint(c
) || (c
== ':') || (c
== '\n'))
2534 return (SMB_LGRP_PGRP_INVALID
);
2536 if (!(islower(c
) || isdigit(c
)))
2540 if ((len
> SMB_LGRP_PGRP_MAXGLEN
- 1) || (badchar
!= 0))
2541 return (SMB_LGRP_PGRP_INVALID
);
2543 if (getgrnam(group
) != NULL
)
2544 return (SMB_LGRP_PGRP_NOTUNIQUE
);
2546 return (SMB_LGRP_PGRP_UNIQUE
);
2552 * Create a posix group with the given name.
2553 * This group will be added to the /etc/group file.
2556 smb_lgrp_pgrp_add(char *group
)
2563 char buf
[SMB_LGRP_PGRP_GRPBUFSIZ
];
2567 rc
= smb_lgrp_pgrp_valid_gname(group
);
2568 if ((rc
== SMB_LGRP_PGRP_INVALID
) || (rc
== SMB_LGRP_PGRP_NOTUNIQUE
))
2571 if ((findnextgid(SMB_LGRP_PGRP_DEFRID
, MAXUID
, &gid
)) != 0)
2574 if ((etcgrp
= fopen(SMB_LGRP_PGRP_GROUP
, "r")) == NULL
)
2577 if (fstat(fileno(etcgrp
), &sb
) < 0)
2578 sb
.st_mode
= S_IRUSR
|S_IWUSR
|S_IRGRP
|S_IROTH
;
2580 o_mask
= umask(077);
2581 etctmp
= fopen(SMB_LGRP_PGRP_GRPTMP
, "w+");
2582 (void) umask(o_mask
);
2584 if (etctmp
== NULL
) {
2585 (void) fclose(etcgrp
);
2589 if (lockf(fileno(etctmp
), F_LOCK
, 0) != 0) {
2590 (void) fclose(etcgrp
);
2591 (void) fclose(etctmp
);
2592 (void) unlink(SMB_LGRP_PGRP_GRPTMP
);
2596 if (fchmod(fileno(etctmp
), sb
.st_mode
) != 0 ||
2597 fchown(fileno(etctmp
), sb
.st_uid
, sb
.st_gid
) != 0) {
2598 (void) lockf(fileno(etctmp
), F_ULOCK
, 0);
2599 (void) fclose(etcgrp
);
2600 (void) fclose(etctmp
);
2601 (void) unlink(SMB_LGRP_PGRP_GRPTMP
);
2605 while (fgets(buf
, SMB_LGRP_PGRP_GRPBUFSIZ
, etcgrp
) != NULL
) {
2606 /* Check for NameService reference */
2607 if (!newdone
&& (buf
[0] == '+' || buf
[0] == '-')) {
2608 (void) fprintf(etctmp
, "%s::%u:\n", group
, gid
);
2612 (void) fputs(buf
, etctmp
);
2614 (void) fclose(etcgrp
);
2617 (void) fprintf(etctmp
, "%s::%u:\n", group
, gid
);
2619 if (rename(SMB_LGRP_PGRP_GRPTMP
, SMB_LGRP_PGRP_GROUP
) < 0) {
2620 (void) lockf(fileno(etctmp
), F_ULOCK
, 0);
2621 (void) fclose(etctmp
);
2622 (void) unlink(SMB_LGRP_PGRP_GRPTMP
);
2626 (void) lockf(fileno(etctmp
), F_ULOCK
, 0);
2627 (void) fclose(etctmp
);