diff options
author | Jean-François Micouleau <jfm@samba.org> | 2001-11-29 16:05:05 +0000 |
---|---|---|
committer | Jean-François Micouleau <jfm@samba.org> | 2001-11-29 16:05:05 +0000 |
commit | fac01bda8bb4f52b930496c362f55aca5b112240 (patch) | |
tree | 14657fee45b97fc453596e62bb9f64e26c26de94 | |
parent | 3a921f37b737cab0729cc904e514647406e6f01c (diff) | |
download | samba-fac01bda8bb4f52b930496c362f55aca5b112240.tar.gz samba-fac01bda8bb4f52b930496c362f55aca5b112240.tar.bz2 samba-fac01bda8bb4f52b930496c362f55aca5b112240.zip |
Changed again how the privilege list is handled in the group mapping code.
This time it's a PRIVILEGE_SET struct instead of a simple uint32 array. It
makes much more sense. Also added a uint32 systemaccount to the GROUP_MAP
struct as some privilege showing in USRMGR.EXE are not real privs but a
bitmask flag. I guess it's an heritage from NT 3.0 ! I could setup an NT
3.1 box to verify, but I'm too lazy (yes I still have my CDs).
Added 3 more LSA calls: SetSystemAccount, AddPrivileges and
RemovePrivileges, we can manage all this privilege from UserManager.
Time to change the NT_USER_TOKEN struct and add checks in all the rpc
functions. Fun, fun, fun.
J.F.
(This used to be commit 3f0a9ef2b8c626cfa2878394bb7b642342342bf3)
-rw-r--r-- | source3/groupdb/mapping.c | 411 | ||||
-rw-r--r-- | source3/include/mapping.h | 10 | ||||
-rw-r--r-- | source3/include/rpc_lsa.h | 42 | ||||
-rw-r--r-- | source3/passdb/passdb.c | 2 | ||||
-rw-r--r-- | source3/rpc_parse/parse_lsa.c | 152 | ||||
-rw-r--r-- | source3/rpc_server/srv_lsa.c | 125 | ||||
-rw-r--r-- | source3/rpc_server/srv_lsa_nt.c | 179 | ||||
-rw-r--r-- | source3/rpc_server/srv_samr_nt.c | 63 | ||||
-rw-r--r-- | source3/utils/smbgroupedit.c | 21 |
9 files changed, 850 insertions, 155 deletions
diff --git a/source3/groupdb/mapping.c b/source3/groupdb/mapping.c index c39bb8cdff..21c9564bd0 100644 --- a/source3/groupdb/mapping.c +++ b/source3/groupdb/mapping.c @@ -66,19 +66,25 @@ PRIVS privs[] = { { 25, "SeUndockPrivilege" }, { 26, "SeSyncAgentPrivilege" }, { 27, "SeEnableDelegationPrivilege" }, -SeNetworkLogonRight -SeUnsolicitedInputPrivilege -SeBatchLogonRight -SeServiceLogonRight -SeInteractiveLogonRight -SeDenyInteractiveLogonRight -SeDenyNetworkLogonRight -SeDenyBatchLogonRight -SeDenyBatchLogonRight - }; */ + /* + * Those are not really privileges like the other ones. + * They are handled in a special case and called + * system privileges. + * + * SeNetworkLogonRight + * SeUnsolicitedInputPrivilege + * SeBatchLogonRight + * SeServiceLogonRight + * SeInteractiveLogonRight + * SeDenyInteractiveLogonRight + * SeDenyNetworkLogonRight + * SeDenyBatchLogonRight + * SeDenyBatchLogonRight + */ + #if 0 /**************************************************************************** check if the user has the required privilege. @@ -173,16 +179,23 @@ BOOL add_mapping_entry(GROUP_MAP *map, int flag) fstring string_sid=""; int len; int i; + PRIVILEGE_SET *set; sid_to_string(string_sid, &map->sid); - len = tdb_pack(buf, sizeof(buf), "ddff", - map->gid, map->sid_name_use, map->nt_name, map->comment); + len = tdb_pack(buf, sizeof(buf), "ddffd", + map->gid, map->sid_name_use, map->nt_name, map->comment, map->systemaccount); - for (i=0; i<PRIV_ALL_INDEX; i++) - len += tdb_pack(buf+len, sizeof(buf)-len, "d", map->privileges[i]); + /* write the privilege list in the TDB database */ - if (len > sizeof(buf)) return False; + set=&map->priv_set; + len += tdb_pack(buf+len, sizeof(buf)-len, "d", set->count); + for (i=0; i<set->count; i++) + len += tdb_pack(buf+len, sizeof(buf)-len, "ddd", + set->set[i].luid.low, set->set[i].luid.high, set->set[i].attr); + + if (len > sizeof(buf)) + return False; slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid); @@ -199,18 +212,19 @@ BOOL add_mapping_entry(GROUP_MAP *map, int flag) initialise first time the mapping list ****************************************************************************/ BOOL add_initial_entry(gid_t gid, fstring sid, enum SID_NAME_USE sid_name_use, - fstring nt_name, fstring comment, uint32 *privilege) + fstring nt_name, fstring comment, PRIVILEGE_SET priv_set, uint32 systemaccount) { GROUP_MAP map; - int i; map.gid=gid; string_to_sid(&map.sid, sid); map.sid_name_use=sid_name_use; fstrcpy(map.nt_name, nt_name); fstrcpy(map.comment, comment); - for (i=0; i<PRIV_ALL_INDEX; i++) - map.privileges[i]=privilege[i]; + map.systemaccount=systemaccount; + + map.priv_set.count=priv_set.count; + map.priv_set.set=priv_set.set; add_mapping_entry(&map, TDB_INSERT); @@ -220,36 +234,59 @@ BOOL add_initial_entry(gid_t gid, fstring sid, enum SID_NAME_USE sid_name_use, /**************************************************************************** initialise a privilege list ****************************************************************************/ -void init_privilege(uint32 *privilege) +void init_privilege(PRIVILEGE_SET *priv_set) { - int i; + priv_set->count=0; + priv_set->control=0; + priv_set->set=NULL; +} - for (i=0; i<PRIV_ALL_INDEX; i++) - privilege[i]=0; +/**************************************************************************** +free a privilege list +****************************************************************************/ +BOOL free_privilege(PRIVILEGE_SET *priv_set) +{ + if (priv_set->count==0) { + DEBUG(10,("free_privilege: count=0, nothing to clear ?\n")); + return False; + } + + if (priv_set->set==NULL) { + DEBUG(0,("free_privilege: list ptr is NULL, very strange !\n")); + return False; + } + + safe_free(priv_set->set); + priv_set->count=0; + priv_set->control=0; + priv_set->set=NULL; } /**************************************************************************** add a privilege to a privilege array ****************************************************************************/ -BOOL add_privilege(uint32 *privilege, uint32 priv) +BOOL add_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set) { - int i=0; - - while (i<PRIV_ALL_INDEX && privilege[i]!=0 && privilege[i]!=priv) - i++; + LUID_ATTR *new_set; - if (i==PRIV_ALL_INDEX) { - DEBUG(10,("add_privilege: the privilege array is full, can't add new priv\n")); + /* check if the privilege is not already in the list */ + if (check_priv_in_privilege(priv_set, set)) return False; - } - if (privilege[i]==priv) { - DEBUG(10,("add_privilege: privilege already in array\n")); + /* we can allocate memory to add the new privilege */ + + new_set=(LUID_ATTR *)Realloc(priv_set->set, (priv_set->count+1)*(sizeof(LUID_ATTR))); + if (new_set==NULL) { + DEBUG(0,("add_privilege: could not Realloc memory to add a new privilege\n")); return False; } - if (privilege[i]==0) - privilege[i]=priv; + new_set[priv_set->count].luid.high=set.luid.high; + new_set[priv_set->count].luid.low=set.luid.low; + new_set[priv_set->count].attr=set.attr; + + priv_set->count++; + priv_set->set=new_set; return True; } @@ -257,41 +294,125 @@ BOOL add_privilege(uint32 *privilege, uint32 priv) /**************************************************************************** add all the privileges to a privilege array ****************************************************************************/ -BOOL add_all_privilege(uint32 *privilege) +BOOL add_all_privilege(PRIVILEGE_SET *priv_set) { - add_privilege(privilege, SE_PRIV_ADD_USERS); - add_privilege(privilege, SE_PRIV_ADD_MACHINES); - add_privilege(privilege, SE_PRIV_PRINT_OPERATOR); + LUID_ATTR set; + + set.attr=0; + set.luid.high=0; + + set.luid.low=SE_PRIV_ADD_USERS; + add_privilege(priv_set, set); + + set.luid.low=SE_PRIV_ADD_MACHINES; + add_privilege(priv_set, set); + + set.luid.low=SE_PRIV_PRINT_OPERATOR; + add_privilege(priv_set, set); + return True; } /**************************************************************************** check if the privilege list is empty ****************************************************************************/ -BOOL check_empty_privilege(uint32 *privilege) +BOOL check_empty_privilege(PRIVILEGE_SET *priv_set) { - int i; - for (i=0; i<PRIV_ALL_INDEX; i++) - if(privilege[i]!=0) - return False; + if (priv_set->count!=0) + return False; + return True; } /**************************************************************************** check if the privilege is in the privilege list ****************************************************************************/ -BOOL check_priv_in_privilege(uint32 *privilege, uint32 priv) +BOOL check_priv_in_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set) { int i; - for (i=0; i<PRIV_ALL_INDEX; i++) - if(privilege[i]==priv) + /* if the list is empty, obviously we can't have it */ + if (check_empty_privilege(priv_set)) + return False; + + for (i=0; i<priv_set->count; i++) { + LUID_ATTR *cur_set; + + cur_set=&priv_set->set[i]; + /* check only the low and high part. Checking the attr field has no meaning */ + if( (cur_set->luid.low==set.luid.low) && (cur_set->luid.high==set.luid.high) ) return True; + } + return False; } /**************************************************************************** +remove a privilege to a privilege array +****************************************************************************/ +BOOL remove_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set) +{ + LUID_ATTR *new_set; + LUID_ATTR *old_set; + int i,j; + + /* check if the privilege is in the list */ + if (!check_priv_in_privilege(priv_set, set)) + return False; + + /* special case if it's the only privilege in the list */ + if (priv_set->count==1) { + free_privilege(priv_set); + init_privilege(priv_set); + + return True; + } + + /* + * the privilege is there, create a new list, + * and copy the other privileges + */ + + old_set=priv_set->set; + + new_set=(LUID_ATTR *)malloc((priv_set->count-1)*(sizeof(LUID_ATTR))); + if (new_set==NULL) { + DEBUG(0,("remove_privilege: could not malloc memory for new privilege list\n")); + return False; + } + + for (i=0, j=0; i<priv_set->count; i++) { + if ((old_set[i].luid.low==set.luid.low) && + (old_set[i].luid.high==set.luid.high)) { + continue; + } + + new_set[j].luid.low=old_set[i].luid.low; + new_set[j].luid.high=old_set[i].luid.high; + new_set[j].attr=old_set[i].attr; + + j++; + } + + if (j!=priv_set->count-1) { + DEBUG(0,("remove_privilege: mismatch ! difference is not -1\n")); + DEBUGADD(0,("old count:%d, new count:%d\n", priv_set->count, j)); + safe_free(new_set); + return False; + } + + /* ok everything is fine */ + + priv_set->count--; + priv_set->set=new_set; + + safe_free(old_set); + + return True; +} + +/**************************************************************************** initialise first time the mapping list ****************************************************************************/ BOOL default_group_mapping(void) @@ -302,49 +423,53 @@ BOOL default_group_mapping(void) fstring str_admins; fstring str_users; fstring str_guests; + LUID_ATTR set; - uint32 privilege_none[PRIV_ALL_INDEX]; - uint32 privilege_all[PRIV_ALL_INDEX]; - uint32 privilege_print_op[PRIV_ALL_INDEX]; + PRIVILEGE_SET privilege_none; + PRIVILEGE_SET privilege_all; + PRIVILEGE_SET privilege_print_op; - init_privilege(privilege_none); - init_privilege(privilege_all); - init_privilege(privilege_print_op); + init_privilege(&privilege_none); + init_privilege(&privilege_all); + init_privilege(&privilege_print_op); - add_privilege(privilege_print_op, SE_PRIV_PRINT_OPERATOR); + set.attr=0; + set.luid.high=0; + set.luid.low=SE_PRIV_PRINT_OPERATOR; + add_privilege(&privilege_print_op, set); - add_all_privilege(privilege_all); + add_all_privilege(&privilege_all); /* Add the Wellknown groups */ - add_initial_entry(-1, "S-1-5-32-544", SID_NAME_WKN_GRP, "Administrators", "", privilege_all); - add_initial_entry(-1, "S-1-5-32-545", SID_NAME_WKN_GRP, "Users", "", privilege_none); - add_initial_entry(-1, "S-1-5-32-546", SID_NAME_WKN_GRP, "Guests", "", privilege_none); - add_initial_entry(-1, "S-1-5-32-547", SID_NAME_WKN_GRP, "Power Users", "", privilege_none); + add_initial_entry(-1, "S-1-5-32-544", SID_NAME_WKN_GRP, "Administrators", "", privilege_all, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY); + add_initial_entry(-1, "S-1-5-32-545", SID_NAME_WKN_GRP, "Users", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY); + add_initial_entry(-1, "S-1-5-32-546", SID_NAME_WKN_GRP, "Guests", "", privilege_none, PR_ACCESS_FROM_NETWORK); + add_initial_entry(-1, "S-1-5-32-547", SID_NAME_WKN_GRP, "Power Users", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY); - add_initial_entry(-1, "S-1-5-32-548", SID_NAME_WKN_GRP, "Account Operators", "", privilege_none); - add_initial_entry(-1, "S-1-5-32-549", SID_NAME_WKN_GRP, "System Operators", "", privilege_none); - add_initial_entry(-1, "S-1-5-32-550", SID_NAME_WKN_GRP, "Print Operators", "", privilege_print_op); - add_initial_entry(-1, "S-1-5-32-551", SID_NAME_WKN_GRP, "Backup Operators", "", privilege_none); + add_initial_entry(-1, "S-1-5-32-548", SID_NAME_WKN_GRP, "Account Operators", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY); + add_initial_entry(-1, "S-1-5-32-549", SID_NAME_WKN_GRP, "System Operators", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY); + add_initial_entry(-1, "S-1-5-32-550", SID_NAME_WKN_GRP, "Print Operators", "", privilege_print_op, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY); + add_initial_entry(-1, "S-1-5-32-551", SID_NAME_WKN_GRP, "Backup Operators", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY); - add_initial_entry(-1, "S-1-5-32-552", SID_NAME_WKN_GRP, "Replicators", "", privilege_none); + add_initial_entry(-1, "S-1-5-32-552", SID_NAME_WKN_GRP, "Replicators", "", privilege_none, PR_ACCESS_FROM_NETWORK); /* Add the defaults domain groups */ sid_copy(&sid_admins, &global_sam_sid); sid_append_rid(&sid_admins, DOMAIN_GROUP_RID_ADMINS); sid_to_string(str_admins, &sid_admins); - add_initial_entry(-1, str_admins, SID_NAME_DOM_GRP, "Domain Admins", "", privilege_all); + add_initial_entry(-1, str_admins, SID_NAME_DOM_GRP, "Domain Admins", "", privilege_all, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY); sid_copy(&sid_users, &global_sam_sid); sid_append_rid(&sid_users, DOMAIN_GROUP_RID_USERS); sid_to_string(str_users, &sid_users); - add_initial_entry(-1, str_users, SID_NAME_DOM_GRP, "Domain Users", "", privilege_none); + add_initial_entry(-1, str_users, SID_NAME_DOM_GRP, "Domain Users", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY); sid_copy(&sid_guests, &global_sam_sid); sid_append_rid(&sid_guests, DOMAIN_GROUP_RID_GUESTS); sid_to_string(str_guests, &sid_guests); - add_initial_entry(-1, str_guests, SID_NAME_DOM_GRP, "Domain Guests", "", privilege_none); + add_initial_entry(-1, str_guests, SID_NAME_DOM_GRP, "Domain Guests", "", privilege_none, PR_ACCESS_FROM_NETWORK); return True; } @@ -360,6 +485,7 @@ BOOL get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map) fstring string_sid; int ret; int i; + PRIVILEGE_SET *set; /* the key is the SID, retrieving is direct */ @@ -372,15 +498,29 @@ BOOL get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map) dbuf = tdb_fetch(tdb, kbuf); if (!dbuf.dptr) return False; - ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff", - &map->gid, &map->sid_name_use, &map->nt_name, &map->comment); + ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd", + &map->gid, &map->sid_name_use, &map->nt_name, &map->comment, &map->systemaccount); + + set=&map->priv_set; + init_privilege(set); + ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count); - for (i=0; i<PRIV_ALL_INDEX; i++) - ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &map->privileges[i]); + DEBUG(10,("get_group_map_from_sid: %d privileges\n", map->priv_set.count)); + + set->set=(LUID_ATTR *)malloc(set->count*sizeof(LUID_ATTR)); + if (set->set==NULL) { + DEBUG(0,("get_group_map_from_sid: could not allocate memory for privileges\n")); + return False; + } + + for (i=0; i<set->count; i++) + ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", + &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr)); SAFE_FREE(dbuf.dptr); if (ret != dbuf.dsize) { DEBUG(0,("get_group_map_from_sid: group mapping TDB corrupted ?\n")); + free_privilege(set); return False; } @@ -399,6 +539,7 @@ BOOL get_group_map_from_gid(gid_t gid, GROUP_MAP *map) fstring string_sid; int ret; int i; + PRIVILEGE_SET *set; /* we need to enumerate the TDB to find the GID */ @@ -415,17 +556,32 @@ BOOL get_group_map_from_gid(gid_t gid, GROUP_MAP *map) string_to_sid(&map->sid, string_sid); - ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff", - &map->gid, &map->sid_name_use, &map->nt_name, &map->comment); + ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd", + &map->gid, &map->sid_name_use, &map->nt_name, &map->comment, &map->systemaccount); + + set=&map->priv_set; + ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count); + + set->set=(LUID_ATTR *)malloc(set->count*sizeof(LUID_ATTR)); + if (set->set==NULL) { + DEBUG(0,("get_group_map_from_sid: could not allocate memory for privileges\n")); + return False; + } - for (i=0; i<PRIV_ALL_INDEX; i++) - ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &map->privileges[i]); + for (i=0; i<set->count; i++) + ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", + &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr)); SAFE_FREE(dbuf.dptr); - if (ret != dbuf.dsize) continue; + if (ret != dbuf.dsize){ + free_privilege(set); + continue; + } if (gid==map->gid) return True; + + free_privilege(set); } return False; @@ -440,8 +596,9 @@ BOOL get_group_map_from_ntname(char *name, GROUP_MAP *map) fstring string_sid; int ret; int i; + PRIVILEGE_SET *set; - /* we need to enumerate the TDB to find the SID */ + /* we need to enumerate the TDB to find the name */ for (kbuf = tdb_firstkey(tdb); kbuf.dptr; @@ -456,25 +613,39 @@ BOOL get_group_map_from_ntname(char *name, GROUP_MAP *map) string_to_sid(&map->sid, string_sid); - ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff", - &map->gid, &map->sid_name_use, &map->nt_name, &map->comment); + ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd", + &map->gid, &map->sid_name_use, &map->nt_name, &map->comment, &map->systemaccount); - for (i=0; i<PRIV_ALL_INDEX; i++) - ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &map->privileges[i]); + set=&map->priv_set; + ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count); + + set->set=(LUID_ATTR *)malloc(set->count*sizeof(LUID_ATTR)); + if (set->set==NULL) { + DEBUG(0,("get_group_map_from_sid: could not allocate memory for privileges\n")); + return False; + } + + for (i=0; i<set->count; i++) + ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", + &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr)); SAFE_FREE(dbuf.dptr); - if (ret != dbuf.dsize) continue; + if (ret != dbuf.dsize) { + free_privilege(set); + continue; + } if (StrCaseCmp(name, map->nt_name)==0) return True; + free_privilege(set); } return False; } /**************************************************************************** -enumerate the group mapping + remove a group mapping entry ****************************************************************************/ BOOL group_map_remove(DOM_SID sid) { @@ -516,6 +687,7 @@ BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, int ret; int entries=0; int i; + PRIVILEGE_SET *set; *num_entries=0; *rmap=NULL; @@ -533,22 +705,42 @@ BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX)); - ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff", - &map.gid, &map.sid_name_use, &map.nt_name, &map.comment); + ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd", + &map.gid, &map.sid_name_use, &map.nt_name, &map.comment, &map.systemaccount); - for (i=0; i<PRIV_ALL_INDEX; i++) - ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &map.privileges[i]); + set=&map.priv_set; + init_privilege(set); + + ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count); + + if (set->count!=0) { + set->set=(LUID_ATTR *)malloc(set->count*sizeof(LUID_ATTR)); + if (set->set==NULL) { + DEBUG(0,("enum_group_mapping: could not allocate memory for privileges\n")); + return False; + } + } + + for (i=0; i<set->count; i++) + ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", + &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr)); SAFE_FREE(dbuf.dptr); - if (ret != dbuf.dsize) + if (ret != dbuf.dsize) { + free_privilege(set); continue; + } /* list only the type or everything if UNKNOWN */ - if (sid_name_use!=SID_NAME_UNKNOWN && sid_name_use!=map.sid_name_use) + if (sid_name_use!=SID_NAME_UNKNOWN && sid_name_use!=map.sid_name_use) { + free_privilege(set); continue; - - if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) + } + + if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) { + free_privilege(set); continue; + } string_to_sid(&map.sid, string_sid); @@ -558,17 +750,21 @@ BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, if (!mapt) { DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n")); SAFE_FREE(*rmap); + free_privilege(set); return False; } - else (*rmap) = mapt; + else + (*rmap) = mapt; mapt[entries].gid = map.gid; sid_copy( &mapt[entries].sid, &map.sid); mapt[entries].sid_name_use = map.sid_name_use; fstrcpy(mapt[entries].nt_name, map.nt_name); fstrcpy(mapt[entries].comment, map.comment); - for (i=0; i<PRIV_ALL_INDEX; i++) - mapt[entries].privileges[i] = map.privileges[i]; + mapt[entries].systemaccount=map.systemaccount; + mapt[entries].priv_set.count=set->count; + mapt[entries].priv_set.control=set->control; + mapt[entries].priv_set.set=set->set; entries++; } @@ -581,11 +777,12 @@ BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, /**************************************************************************** convert a privilege string to a privilege array ****************************************************************************/ -void convert_priv_from_text(uint32 *se_priv, char *privilege) +void convert_priv_from_text(PRIVILEGE_SET *se_priv, char *privilege) { pstring tok; char *p = privilege; int i; + LUID_ATTR set; /* By default no privilege */ init_privilege(se_priv); @@ -595,8 +792,12 @@ void convert_priv_from_text(uint32 *se_priv, char *privilege) while(next_token(&p, tok, " ", sizeof(tok)) ) { for (i=0; i<=PRIV_ALL_INDEX; i++) { - if (StrCaseCmp(privs[i].priv, tok)==0) - add_privilege(se_priv, privs[i].se_priv); + if (StrCaseCmp(privs[i].priv, tok)==0) { + set.attr=0; + set.luid.high=0; + set.luid.low=privs[i].se_priv; + add_privilege(se_priv, set); + } } } } @@ -604,9 +805,9 @@ void convert_priv_from_text(uint32 *se_priv, char *privilege) /**************************************************************************** convert a privilege array to a privilege string ****************************************************************************/ -void convert_priv_to_text(uint32 *se_priv, char *privilege) +void convert_priv_to_text(PRIVILEGE_SET *se_priv, char *privilege) { - int i=0,j; + int i,j; if (privilege==NULL) return; @@ -618,14 +819,14 @@ void convert_priv_to_text(uint32 *se_priv, char *privilege) return; } - while(i<PRIV_ALL_INDEX && se_priv[i]!=0) { + for(i=0; i<se_priv->count; i++) { j=1; - while (privs[j].se_priv!=se_priv[i]) + while (privs[j].se_priv!=se_priv->set[i].luid.low && j<=PRIV_ALL_INDEX) { j++; + } fstrcat(privilege, privs[j].priv); fstrcat(privilege, " "); - i++; } } @@ -702,11 +903,12 @@ BOOL get_local_group_from_sid(DOM_SID sid, GROUP_MAP *map) return False; map->sid_name_use=SID_NAME_ALIAS; + map->systemaccount=PR_ACCESS_FROM_NETWORK; fstrcpy(map->nt_name, grp->gr_name); fstrcpy(map->comment, "Local Unix Group"); - init_privilege(map->privileges); + init_privilege(&map->priv_set); sid_copy(&map->sid, &sid); } @@ -753,7 +955,8 @@ BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map) if (!get_group_map_from_gid(gid, map)) { map->gid=gid; map->sid_name_use=SID_NAME_ALIAS; - init_privilege(map->privileges); + map->systemaccount=PR_ACCESS_FROM_NETWORK; + init_privilege(&map->priv_set); sid_copy(&map->sid, &global_sam_sid); sid_append_rid(&map->sid, pdb_gid_to_group_rid(gid)); diff --git a/source3/include/mapping.h b/source3/include/mapping.h index 9a64eefa56..4a7db6360d 100644 --- a/source3/include/mapping.h +++ b/source3/include/mapping.h @@ -33,13 +33,21 @@ #define ENUM_ONLY_MAPPED True #define ENUM_ALL_MAPPED False +#define PR_NONE 0x0000 +#define PR_LOG_ON_LOCALLY 0x0001 +#define PR_ACCESS_FROM_NETWORK 0x0002 +#define PR_LOG_ON_BATCH_JOB 0x0004 +#define PR_LOG_ON_SERVICE 0x0010 + + typedef struct _GROUP_MAP { gid_t gid; DOM_SID sid; enum SID_NAME_USE sid_name_use; fstring nt_name; fstring comment; - uint32 privileges[PRIV_ALL_INDEX]; + uint32 systemaccount; + PRIVILEGE_SET priv_set; } GROUP_MAP; typedef struct _PRIVS { diff --git a/source3/include/rpc_lsa.h b/source3/include/rpc_lsa.h index f3edac6873..ce275d4ace 100644 --- a/source3/include/rpc_lsa.h +++ b/source3/include/rpc_lsa.h @@ -570,6 +570,18 @@ typedef struct lsa_r_getsystemaccount } LSA_R_GETSYSTEMACCOUNT; +typedef struct lsa_q_setsystemaccount +{ + POLICY_HND pol; /* policy handle */ + uint32 access; +} LSA_Q_SETSYSTEMACCOUNT; + +typedef struct lsa_r_setsystemaccount +{ + NTSTATUS status; +} LSA_R_SETSYSTEMACCOUNT; + + typedef struct lsa_q_lookupprivvalue { POLICY_HND pol; /* policy handle */ @@ -583,6 +595,36 @@ typedef struct lsa_r_lookupprivvalue NTSTATUS status; } LSA_R_LOOKUPPRIVVALUE; + +typedef struct lsa_q_addprivs +{ + POLICY_HND pol; /* policy handle */ + uint32 count; + PRIVILEGE_SET set; +} LSA_Q_ADDPRIVS; + +typedef struct lsa_r_addprivs +{ + NTSTATUS status; +} LSA_R_ADDPRIVS; + + +typedef struct lsa_q_removeprivs +{ + POLICY_HND pol; /* policy handle */ + uint32 allrights; + uint32 ptr; + uint32 count; + PRIVILEGE_SET set; +} LSA_Q_REMOVEPRIVS; + +typedef struct lsa_r_removeprivs +{ + NTSTATUS status; +} LSA_R_REMOVEPRIVS; + + + #endif /* _RPC_LSA_H */ /* diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 873e569f68..b07dec7c0d 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -551,6 +551,7 @@ BOOL local_lookup_rid(uint32 rid, char *name, enum SID_NAME_USE *psid_name_use) /* check if it's a mapped group */ if (get_group_map_from_sid(local_sid, &map)) { + free_privilege(&map.priv_set); if (map.gid!=-1) { DEBUG(5,("local_local_rid: mapped group %s to gid %u\n", map.nt_name, (unsigned int)map.gid)); fstrcpy(name, map.nt_name); @@ -636,6 +637,7 @@ BOOL local_lookup_name(const char *c_domain, const char *c_user, DOM_SID *psid, /* check if it's a mapped group */ if (get_group_map_from_ntname(user, &map)) { + free_privilege(&map.priv_set); if (map.gid!=-1) { /* yes it's a mapped group to a valid unix group */ sid_copy(&local_sid, &map.sid); diff --git a/source3/rpc_parse/parse_lsa.c b/source3/rpc_parse/parse_lsa.c index b5f51de697..90fa8d8fff 100644 --- a/source3/rpc_parse/parse_lsa.c +++ b/source3/rpc_parse/parse_lsa.c @@ -1814,6 +1814,7 @@ void init_lsa_r_enum_privsaccount(LSA_R_ENUMPRIVSACCOUNT *r_u, LUID_ATTR *set, u r_u->set.set=set; r_u->set.count=count; r_u->set.control=control; + DEBUG(10,("init_lsa_r_enum_privsaccount: %d %d privileges\n", r_u->count, r_u->set.count)); } /******************************************************************* @@ -1894,6 +1895,47 @@ BOOL lsa_io_r_getsystemaccount(char *desc, LSA_R_GETSYSTEMACCOUNT *r_c, prs_str return True; } + +/******************************************************************* + Reads or writes an LSA_Q_SETSYSTEMACCOUNT structure. +********************************************************************/ + +BOOL lsa_io_q_setsystemaccount(char *desc, LSA_Q_SETSYSTEMACCOUNT *r_c, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "lsa_io_q_setsystemaccount"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_pol_hnd("pol", &r_c->pol, ps, depth)) + return False; + + if(!prs_uint32("access", ps, depth, &r_c->access)) + return False; + + return True; +} + +/******************************************************************* + Reads or writes an LSA_R_SETSYSTEMACCOUNT structure. +********************************************************************/ + +BOOL lsa_io_r_setsystemaccount(char *desc, LSA_R_SETSYSTEMACCOUNT *r_c, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "lsa_io_r_setsystemaccount"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_ntstatus("status", ps, depth, &r_c->status)) + return False; + + return True; +} + + void init_lsa_q_lookupprivvalue(LSA_Q_LOOKUPPRIVVALUE *trn, POLICY_HND *hnd, char *name) { int len_name = strlen(name); @@ -1948,3 +1990,113 @@ BOOL lsa_io_r_lookupprivvalue(char *desc, LSA_R_LOOKUPPRIVVALUE *r_c, prs_struc return True; } + + +/******************************************************************* + Reads or writes an LSA_Q_ADDPRIVS structure. +********************************************************************/ + +BOOL lsa_io_q_addprivs(char *desc, LSA_Q_ADDPRIVS *r_c, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "lsa_io_q_addprivs"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_pol_hnd("pol", &r_c->pol, ps, depth)) + return False; + + if(!prs_uint32("count", ps, depth, &r_c->count)) + return False; + + if (UNMARSHALLING(ps) && r_c->count!=0) { + if (!(r_c->set.set = (LUID_ATTR *)prs_alloc_mem(ps,sizeof(LUID_ATTR) * r_c->count))) + return False; + } + + if(!lsa_io_privilege_set(desc, &r_c->set, ps, depth)) + return False; + + return True; +} + +/******************************************************************* + Reads or writes an LSA_R_ADDPRIVS structure. +********************************************************************/ + +BOOL lsa_io_r_addprivs(char *desc, LSA_R_ADDPRIVS *r_c, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "lsa_io_r_addprivs"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_ntstatus("status", ps, depth, &r_c->status)) + return False; + + return True; +} + +/******************************************************************* + Reads or writes an LSA_Q_REMOVEPRIVS structure. +********************************************************************/ + +BOOL lsa_io_q_removeprivs(char *desc, LSA_Q_REMOVEPRIVS *r_c, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "lsa_io_q_removeprivs"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_pol_hnd("pol", &r_c->pol, ps, depth)) + return False; + + if(!prs_uint32("allrights", ps, depth, &r_c->allrights)) + return False; + + if(!prs_uint32("ptr", ps, depth, &r_c->ptr)) + return False; + + /* + * JFM: I'm not sure at all if the count is inside the ptr + * never seen one with ptr=0 + */ + + if (r_c->ptr!=0) { + if(!prs_uint32("count", ps, depth, &r_c->count)) + return False; + + if (UNMARSHALLING(ps) && r_c->count!=0) { + if (!(r_c->set.set = (LUID_ATTR *)prs_alloc_mem(ps,sizeof(LUID_ATTR) * r_c->count))) + return False; + } + + if(!lsa_io_privilege_set(desc, &r_c->set, ps, depth)) + return False; + } + + return True; +} + +/******************************************************************* + Reads or writes an LSA_R_REMOVEPRIVS structure. +********************************************************************/ + +BOOL lsa_io_r_removeprivs(char *desc, LSA_R_REMOVEPRIVS *r_c, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "lsa_io_r_removeprivs"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_ntstatus("status", ps, depth, &r_c->status)) + return False; + + return True; +} + + diff --git a/source3/rpc_server/srv_lsa.c b/source3/rpc_server/srv_lsa.c index 4331ffca8d..d2b2c60f45 100644 --- a/source3/rpc_server/srv_lsa.c +++ b/source3/rpc_server/srv_lsa.c @@ -482,27 +482,124 @@ static BOOL api_lsa_getsystemaccount(pipes_struct *p) /*************************************************************************** + api_lsa_setsystemaccount + ***************************************************************************/ + +static BOOL api_lsa_setsystemaccount(pipes_struct *p) +{ + LSA_Q_SETSYSTEMACCOUNT q_u; + LSA_R_SETSYSTEMACCOUNT r_u; + + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!lsa_io_q_setsystemaccount("", &q_u, data, 0)) { + DEBUG(0,("api_lsa_setsystemaccount: failed to unmarshall LSA_Q_SETSYSTEMACCOUNT.\n")); + return False; + } + + r_u.status = _lsa_setsystemaccount(p, &q_u, &r_u); + + /* store the response in the SMB stream */ + if(!lsa_io_r_setsystemaccount("", &r_u, rdata, 0)) { + DEBUG(0,("api_lsa_setsystemaccount: Failed to marshall LSA_R_SETSYSTEMACCOUNT.\n")); + return False; + } + + return True; +} + +/*************************************************************************** + api_lsa_addprivs + ***************************************************************************/ + +static BOOL api_lsa_addprivs(pipes_struct *p) +{ + LSA_Q_ADDPRIVS q_u; + LSA_R_ADDPRIVS r_u; + + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!lsa_io_q_addprivs("", &q_u, data, 0)) { + DEBUG(0,("api_lsa_addprivs: failed to unmarshall LSA_Q_ADDPRIVS.\n")); + return False; + } + + r_u.status = _lsa_addprivs(p, &q_u, &r_u); + + /* store the response in the SMB stream */ + if(!lsa_io_r_addprivs("", &r_u, rdata, 0)) { + DEBUG(0,("api_lsa_addprivs: Failed to marshall LSA_R_ADDPRIVS.\n")); + return False; + } + + return True; +} + +/*************************************************************************** + api_lsa_removeprivs + ***************************************************************************/ + +static BOOL api_lsa_removeprivs(pipes_struct *p) +{ + LSA_Q_REMOVEPRIVS q_u; + LSA_R_REMOVEPRIVS r_u; + + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!lsa_io_q_removeprivs("", &q_u, data, 0)) { + DEBUG(0,("api_lsa_removeprivs: failed to unmarshall LSA_Q_REMOVEPRIVS.\n")); + return False; + } + + r_u.status = _lsa_removeprivs(p, &q_u, &r_u); + + /* store the response in the SMB stream */ + if(!lsa_io_r_removeprivs("", &r_u, rdata, 0)) { + DEBUG(0,("api_lsa_removeprivs: Failed to marshall LSA_R_REMOVEPRIVS.\n")); + return False; + } + + return True; +} + + +/*************************************************************************** \PIPE\ntlsa commands ***************************************************************************/ static struct api_struct api_lsa_cmds[] = { - { "LSA_OPENPOLICY2" , LSA_OPENPOLICY2 , api_lsa_open_policy2 }, - { "LSA_OPENPOLICY" , LSA_OPENPOLICY , api_lsa_open_policy }, - { "LSA_QUERYINFOPOLICY" , LSA_QUERYINFOPOLICY , api_lsa_query_info }, - { "LSA_ENUMTRUSTDOM" , LSA_ENUMTRUSTDOM , api_lsa_enum_trust_dom }, - { "LSA_CLOSE" , LSA_CLOSE , api_lsa_close }, - { "LSA_OPENSECRET" , LSA_OPENSECRET , api_lsa_open_secret }, - { "LSA_LOOKUPSIDS" , LSA_LOOKUPSIDS , api_lsa_lookup_sids }, - { "LSA_LOOKUPNAMES" , LSA_LOOKUPNAMES , api_lsa_lookup_names }, - { "LSA_ENUM_PRIVS" , LSA_ENUM_PRIVS , api_lsa_enum_privs }, + { "LSA_OPENPOLICY2" , LSA_OPENPOLICY2 , api_lsa_open_policy2 }, + { "LSA_OPENPOLICY" , LSA_OPENPOLICY , api_lsa_open_policy }, + { "LSA_QUERYINFOPOLICY" , LSA_QUERYINFOPOLICY , api_lsa_query_info }, + { "LSA_ENUMTRUSTDOM" , LSA_ENUMTRUSTDOM , api_lsa_enum_trust_dom }, + { "LSA_CLOSE" , LSA_CLOSE , api_lsa_close }, + { "LSA_OPENSECRET" , LSA_OPENSECRET , api_lsa_open_secret }, + { "LSA_LOOKUPSIDS" , LSA_LOOKUPSIDS , api_lsa_lookup_sids }, + { "LSA_LOOKUPNAMES" , LSA_LOOKUPNAMES , api_lsa_lookup_names }, + { "LSA_ENUM_PRIVS" , LSA_ENUM_PRIVS , api_lsa_enum_privs }, { "LSA_PRIV_GET_DISPNAME",LSA_PRIV_GET_DISPNAME,api_lsa_priv_get_dispname}, - { "LSA_ENUM_ACCOUNTS" , LSA_ENUM_ACCOUNTS , api_lsa_enum_accounts }, - { "LSA_UNK_GET_CONNUSER", LSA_UNK_GET_CONNUSER, api_lsa_unk_get_connuser}, - { "LSA_OPENACCOUNT" , LSA_OPENACCOUNT , api_lsa_open_account }, + { "LSA_ENUM_ACCOUNTS" , LSA_ENUM_ACCOUNTS , api_lsa_enum_accounts }, + { "LSA_UNK_GET_CONNUSER", LSA_UNK_GET_CONNUSER, api_lsa_unk_get_connuser }, + { "LSA_OPENACCOUNT" , LSA_OPENACCOUNT , api_lsa_open_account }, { "LSA_ENUMPRIVSACCOUNT", LSA_ENUMPRIVSACCOUNT, api_lsa_enum_privsaccount}, - { "LSA_GETSYSTEMACCOUNT", LSA_GETSYSTEMACCOUNT, api_lsa_getsystemaccount}, - { NULL , 0 , NULL } + { "LSA_GETSYSTEMACCOUNT", LSA_GETSYSTEMACCOUNT, api_lsa_getsystemaccount }, + { "LSA_SETSYSTEMACCOUNT", LSA_SETSYSTEMACCOUNT, api_lsa_setsystemaccount }, + { "LSA_ADDPRIVS" , LSA_ADDPRIVS , api_lsa_addprivs }, + { "LSA_REMOVEPRIVS" , LSA_REMOVEPRIVS , api_lsa_removeprivs }, + { NULL , 0 , NULL } }; /*************************************************************************** diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index bf5d24188e..b16e3836f6 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -563,7 +563,7 @@ NTSTATUS _lsa_enum_privs(pipes_struct *p, LSA_Q_ENUM_PRIVS *q_u, LSA_R_ENUM_PRIV init_uni_hdr(&entry->hdr_name, strlen(privs[i+1].priv)); init_unistr2(&entry->name, privs[i+1].priv, strlen(privs[i+1].priv) ); entry->luid_low = privs[i+1].se_priv; - entry->luid_high = 1; + entry->luid_high = 0; } } @@ -601,7 +601,7 @@ NTSTATUS _lsa_priv_get_dispname(pipes_struct *p, LSA_Q_PRIV_GET_DISPNAME *q_u, L r_u->lang_id=q_u->lang_id; return NT_STATUS_OK; } else { - DEBUG(10,(": doesn't exist\n")); + DEBUG(10,("_lsa_priv_get_dispname: doesn't exist\n")); r_u->ptr_info=0; return NT_STATUS_NO_SUCH_PRIVILEGE; } @@ -717,7 +717,6 @@ NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, LSA_Q_ENUMPRIVSACCOUNT *q_u, LS { struct lsa_info *info=NULL; GROUP_MAP map; - uint32 count=0; int i=0; LUID_ATTR *set=NULL; @@ -731,21 +730,26 @@ NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, LSA_Q_ENUMPRIVSACCOUNT *q_u, LS if (!get_group_map_from_sid(info->sid, &map)) return NT_STATUS_NO_SUCH_GROUP; - for (i=1; privs[i].se_priv!=SE_PRIV_ALL; i++) { - if ( check_priv_in_privilege(map.privileges, privs[i].se_priv)) { - - set=(LUID_ATTR *)talloc_realloc(p->mem_ctx, set, (count+1)*sizeof(LUID_ATTR)); - if (set == NULL) return NT_STATUS_NO_MEMORY; - - set[count].luid.low=privs[i].se_priv; - set[count].luid.high=1; - set[count].attr=0; - - count++; + DEBUG(10,("_lsa_enum_privsaccount: %d privileges\n", map.priv_set.count)); + if (map.priv_set.count!=0) { + + set=(LUID_ATTR *)talloc(p->mem_ctx, map.priv_set.count*sizeof(LUID_ATTR)); + if (set == NULL) { + free_privilege(&map.priv_set); + return NT_STATUS_NO_MEMORY; + } + + for (i=0; i<map.priv_set.count; i++) { + set[i].luid.low=map.priv_set.set[i].luid.low; + set[i].luid.high=map.priv_set.set[i].luid.high; + set[i].attr=map.priv_set.set[i].attr; + DEBUG(10,("_lsa_enum_privsaccount: priv %d: %d:%d:%d\n", i, + set[i].luid.high, set[i].luid.low, set[i].attr)); } } - init_lsa_r_enum_privsaccount(r_u, set, count, 0); + init_lsa_r_enum_privsaccount(r_u, set, map.priv_set.count, 0); + free_privilege(&map.priv_set); return r_u->status; } @@ -756,13 +760,154 @@ NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, LSA_Q_ENUMPRIVSACCOUNT *q_u, LS NTSTATUS _lsa_getsystemaccount(pipes_struct *p, LSA_Q_GETSYSTEMACCOUNT *q_u, LSA_R_GETSYSTEMACCOUNT *r_u) { + struct lsa_info *info=NULL; + GROUP_MAP map; r_u->status = NT_STATUS_OK; /* find the connection policy handle. */ - if (!find_policy_by_hnd(p, &q_u->pol, NULL)) + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; - r_u->access=3; + if (!get_group_map_from_sid(info->sid, &map)) + return NT_STATUS_NO_SUCH_GROUP; + + /* + 0x01 -> Log on locally + 0x02 -> Access this computer from network + 0x04 -> Log on as a batch job + 0x10 -> Log on as a service + + they can be ORed together + */ + + r_u->access=map.systemaccount; return r_u->status; } + +/*************************************************************************** + update the systemaccount information + ***************************************************************************/ + +NTSTATUS _lsa_setsystemaccount(pipes_struct *p, LSA_Q_SETSYSTEMACCOUNT *q_u, LSA_R_SETSYSTEMACCOUNT *r_u) +{ + struct lsa_info *info=NULL; + GROUP_MAP map; + r_u->status = NT_STATUS_OK; + + /* find the connection policy handle. */ + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) + return NT_STATUS_INVALID_HANDLE; + + if (!get_group_map_from_sid(info->sid, &map)) + return NT_STATUS_NO_SUCH_GROUP; + + map.systemaccount=q_u->access; + + if(!add_mapping_entry(&map, TDB_REPLACE)) + return NT_STATUS_NO_SUCH_GROUP; + + return r_u->status; +} + +/*************************************************************************** + For a given SID, add some privileges. + ***************************************************************************/ + +NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u) +{ + struct lsa_info *info=NULL; + GROUP_MAP map; + int i=0; + + LUID_ATTR *luid_attr=NULL; + PRIVILEGE_SET *set=NULL; + + r_u->status = NT_STATUS_OK; + + /* find the connection policy handle. */ + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) + return NT_STATUS_INVALID_HANDLE; + + if (!get_group_map_from_sid(info->sid, &map)) + return NT_STATUS_NO_SUCH_GROUP; + + set=&q_u->set; + + for (i=0; i<set->count; i++) { + luid_attr=&set->set[i]; + + /* check if the privilege is already there */ + if (check_priv_in_privilege(&map.priv_set, *luid_attr)){ + free_privilege(&map.priv_set); + return NT_STATUS_NO_SUCH_PRIVILEGE; + } + + add_privilege(&map.priv_set, *luid_attr); + } + + if(!add_mapping_entry(&map, TDB_REPLACE)) + return NT_STATUS_NO_SUCH_GROUP; + + free_privilege(&map.priv_set); + + return r_u->status; +} + +/*************************************************************************** + For a given SID, remove some privileges. + ***************************************************************************/ + +NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEPRIVS *r_u) +{ + struct lsa_info *info=NULL; + GROUP_MAP map; + int i=0; + + LUID_ATTR *luid_attr=NULL; + PRIVILEGE_SET *set=NULL; + + r_u->status = NT_STATUS_OK; + + /* find the connection policy handle. */ + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) + return NT_STATUS_INVALID_HANDLE; + + if (!get_group_map_from_sid(info->sid, &map)) + return NT_STATUS_NO_SUCH_GROUP; + + if (q_u->allrights!=0) { + /* log it and return, until I see one myself don't do anything */ + DEBUG(5,("_lsa_removeprivs: trying to remove all privileges ?\n")); + return NT_STATUS_OK; + } + + if (q_u->ptr==0) { + /* log it and return, until I see one myself don't do anything */ + DEBUG(5,("_lsa_removeprivs: no privileges to remove ?\n")); + return NT_STATUS_OK; + } + + set=&q_u->set; + + for (i=0; i<set->count; i++) { + luid_attr=&set->set[i]; + + /* if we don't have the privilege, we're trying to remove, give up */ + /* what else can we do ??? JFM. */ + if (!check_priv_in_privilege(&map.priv_set, *luid_attr)){ + free_privilege(&map.priv_set); + return NT_STATUS_NO_SUCH_PRIVILEGE; + } + + remove_privilege(&map.priv_set, *luid_attr); + } + + if(!add_mapping_entry(&map, TDB_REPLACE)) + return NT_STATUS_NO_SUCH_GROUP; + + free_privilege(&map.priv_set); + + return r_u->status; +} + diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 12b37834d8..112b1bb293 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -813,13 +813,16 @@ static NTSTATUS get_group_alias_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DOM enum_group_mapping(SID_NAME_WKN_GRP, &map, (int *)&num_entries, ENUM_ONLY_MAPPED); if (num_entries != 0) { + for (i=0; i<num_entries; i++) + free_privilege(&(map[i].priv_set)); + *d_grp=(DOMAIN_GRP *)talloc_zero(ctx, num_entries*sizeof(DOMAIN_GRP)); if (*d_grp==NULL) return NT_STATUS_NO_MEMORY; for(i=0; i<num_entries && i<max_entries; i++) { fstrcpy((*d_grp)[i].name, map[i+start_idx].nt_name); - sid_split_rid(&map[i].sid, &(*d_grp)[i].rid); + sid_split_rid(&map[i+start_idx].sid, &(*d_grp)[i].rid); } } @@ -851,6 +854,12 @@ static NTSTATUS get_group_alias_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DOM continue; } + /* + * free early the privilege struct as it's not used + * and prevent leaking mem. + */ + free_privilege(&smap.priv_set); + if (smap.sid_name_use!=SID_NAME_ALIAS) { continue; } @@ -873,8 +882,9 @@ static NTSTATUS get_group_alias_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DOM if ( (*d_grp)[i].rid == trid ) break; - if ( i < num_entries ) + if ( i < num_entries ) { continue; /* rid was there, dup! */ + } /* JRA - added this for large group db enumeration... */ @@ -925,6 +935,13 @@ static NTSTATUS get_group_domain_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DO *p_num_entries = 0; enum_group_mapping(SID_NAME_DOM_GRP, &map, (int *)&group_entries, ENUM_ONLY_MAPPED); + + /* + * free early the privilege struct as it's not used + * and prevent leaking mem. + */ + for (i=0; i<group_entries; i++) + free_privilege(&(map[i].priv_set)); num_entries=group_entries-start_idx; @@ -2702,6 +2719,8 @@ NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_ } } + free_privilege(&map.priv_set); + if(!get_uid_list_of_group(map.gid, &uid, &num_uids)) return NT_STATUS_NO_SUCH_ALIAS; @@ -2762,6 +2781,8 @@ NTSTATUS _samr_query_groupmem(pipes_struct *p, SAMR_Q_QUERY_GROUPMEM *q_u, SAMR_ if(!get_domain_group_from_sid(group_sid, &map)) return NT_STATUS_NO_SUCH_GROUP; + free_privilege(&map.priv_set); + if(!get_uid_list_of_group(map.gid, &uid, &num_uids)) return NT_STATUS_NO_SUCH_GROUP; @@ -2817,7 +2838,9 @@ NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_AD } else return NT_STATUS_NO_SUCH_ALIAS; } - + + free_privilege(&map.priv_set); + sid_split_rid(&q_u->sid.sid, &rid); uid=pdb_user_rid_to_uid(rid); @@ -2885,6 +2908,8 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD if(!get_domain_group_from_sid(group_sid, &map)) return NT_STATUS_NO_SUCH_GROUP; + free_privilege(&map.priv_set); + if ((pwd=getpwuid(pdb_user_rid_to_uid(q_u->rid))) ==NULL) return NT_STATUS_NO_SUCH_USER; @@ -2968,6 +2993,8 @@ NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, S if(!get_domain_group_from_sid(group_sid, &map)) return NT_STATUS_NO_SUCH_ALIAS; + free_privilege(&map.priv_set); + gid=map.gid; /* check if group really exists */ @@ -3025,6 +3052,8 @@ NTSTATUS _samr_delete_dom_alias(pipes_struct *p, SAMR_Q_DELETE_DOM_ALIAS *q_u, S if(!get_local_group_from_sid(alias_sid, &map)) return NT_STATUS_NO_SUCH_ALIAS; + free_privilege(&map.priv_set); + gid=map.gid; /* check if group really exists */ @@ -3059,6 +3088,9 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S fstring sid_string; struct group *grp; struct samr_info *info; + PRIVILEGE_SET priv_set; + + init_privilege(&priv_set); /* Find the policy handle. Open a policy on it. */ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &dom_sid)) @@ -3085,7 +3117,7 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S r_u->rid=pdb_gid_to_group_rid(grp->gr_gid); /* add the group to the mapping table */ - if(!add_initial_entry(grp->gr_gid, sid_string, SID_NAME_DOM_GRP, name, NULL, SE_PRIV_NONE)) + if(!add_initial_entry(grp->gr_gid, sid_string, SID_NAME_DOM_GRP, name, NULL, priv_set, PR_ACCESS_FROM_NETWORK)) return NT_STATUS_ACCESS_DENIED; if ((info = (struct samr_info *)malloc(sizeof(struct samr_info))) == NULL) @@ -3115,6 +3147,9 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S fstring sid_string; struct group *grp; struct samr_info *info; + PRIVILEGE_SET priv_set; + + init_privilege(&priv_set); /* Find the policy handle. Open a policy on it. */ if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &dom_sid)) @@ -3150,7 +3185,7 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S sid_to_string(sid_string, &info->sid); /* add the group to the mapping table */ - if(!add_initial_entry(grp->gr_gid, sid_string, SID_NAME_ALIAS, name, NULL, SE_PRIV_NONE)) + if(!add_initial_entry(grp->gr_gid, sid_string, SID_NAME_ALIAS, name, NULL, priv_set, PR_ACCESS_FROM_NETWORK)) return NT_STATUS_ACCESS_DENIED; /* get a (unique) handle. open a policy on it. */ @@ -3180,6 +3215,8 @@ NTSTATUS _samr_query_groupinfo(pipes_struct *p, SAMR_Q_QUERY_GROUPINFO *q_u, SAM if (!get_domain_group_from_sid(group_sid, &map)) return NT_STATUS_INVALID_HANDLE; + + free_privilege(&map.priv_set); ctr=(GROUP_INFO_CTR *)talloc_zero(p->mem_ctx, sizeof(GROUP_INFO_CTR)); if (ctr==NULL) @@ -3234,11 +3271,16 @@ NTSTATUS _samr_set_groupinfo(pipes_struct *p, SAMR_Q_SET_GROUPINFO *q_u, SAMR_R_ unistr2_to_ascii(map.comment, &(ctr->group.info4.uni_acct_desc), sizeof(map.comment)-1); break; default: + free_privilege(&map.priv_set); return NT_STATUS_INVALID_INFO_CLASS; } - if(!add_mapping_entry(&map, TDB_REPLACE)) + if(!add_mapping_entry(&map, TDB_REPLACE)) { + free_privilege(&map.priv_set); return NT_STATUS_NO_SUCH_GROUP; + } + + free_privilege(&map.priv_set); return NT_STATUS_OK; } @@ -3268,11 +3310,16 @@ NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_ unistr2_to_ascii(map.comment, &(ctr->alias.info3.uni_acct_desc), sizeof(map.comment)-1); break; default: + free_privilege(&map.priv_set); return NT_STATUS_INVALID_INFO_CLASS; } - if(!add_mapping_entry(&map, TDB_REPLACE)) + if(!add_mapping_entry(&map, TDB_REPLACE)) { + free_privilege(&map.priv_set); return NT_STATUS_NO_SUCH_GROUP; + } + + free_privilege(&map.priv_set); return NT_STATUS_OK; } @@ -3320,6 +3367,8 @@ NTSTATUS _samr_open_group(pipes_struct *p, SAMR_Q_OPEN_GROUP *q_u, SAMR_R_OPEN_G if (!get_domain_group_from_sid(info->sid, &map)) return NT_STATUS_NO_SUCH_USER; + free_privilege(&map.priv_set); + /* get a (unique) handle. open a policy on it. */ if (!create_policy_hnd(p, &r_u->pol, free_samr_info, (void *)info)) return NT_STATUS_OBJECT_NAME_NOT_FOUND; diff --git a/source3/utils/smbgroupedit.c b/source3/utils/smbgroupedit.c index b6138fa576..9d42d2fc92 100644 --- a/source3/utils/smbgroupedit.c +++ b/source3/utils/smbgroupedit.c @@ -62,7 +62,7 @@ static void usage(void) **********************************************************/ int addgroup(char *group, enum SID_NAME_USE sid_type, char *ntgroup, char *ntcomment, char *privilege) { - uint32 se_priv[PRIV_ALL_INDEX]; + PRIVILEGE_SET se_priv; gid_t gid; DOM_SID sid; fstring string_sid; @@ -85,11 +85,11 @@ int addgroup(char *group, enum SID_NAME_USE sid_type, char *ntgroup, char *ntcom else fstrcpy(comment, ntcomment); - init_privilege(se_priv); + init_privilege(&se_priv); if (privilege!=NULL) - convert_priv_from_text(se_priv, privilege); + convert_priv_from_text(&se_priv, privilege); - if(!add_initial_entry(gid, string_sid, sid_type, name, comment, se_priv)) + if(!add_initial_entry(gid, string_sid, sid_type, name, comment, se_priv, PR_ACCESS_FROM_NETWORK)) return -1; return 0; @@ -103,7 +103,7 @@ int changegroup(char *sid_string, char *group, enum SID_NAME_USE sid_type, char DOM_SID sid; GROUP_MAP map; gid_t gid; - uint32 se_priv[PRIV_ALL_INDEX]; + PRIVILEGE_SET se_priv; string_to_sid(&sid, sid_string); @@ -140,12 +140,8 @@ int changegroup(char *sid_string, char *group, enum SID_NAME_USE sid_type, char fstrcpy(map.comment, groupdesc); /* Change the privilege if new one */ - if (privilege!=NULL) { - int i; - convert_priv_from_text(se_priv, privilege); - for(i=0; i<PRIV_ALL_INDEX; i++) - map.privileges[i]=se_priv[i]; - } + if (privilege!=NULL) + convert_priv_from_text(&map.priv_set, privilege); if (!add_mapping_entry(&map, TDB_REPLACE)) { printf("Count not update group database\n"); @@ -190,7 +186,8 @@ int listgroup(enum SID_NAME_USE sid_type, BOOL long_list) for (i=0; i<entries; i++) { decode_sid_name_use(group_type, (map[i]).sid_name_use); sid_to_string(string_sid, &map[i].sid); - convert_priv_to_text(map[i].privileges, priv_text); + convert_priv_to_text(&(map[i].priv_set), priv_text); + free_privilege(&(map[i].priv_set)); if (!long_list) printf("%s (%s) -> %s\n", map[i].nt_name, string_sid, gidtoname(map[i].gid)); |