1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-27 03:21:53 +03:00
samba-mirror/source3/rpc_server/srv_util.c

425 lines
12 KiB
C
Raw Normal View History

/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1998
* Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
* Copyright (C) Paul Ashton 1997-1998.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* this module apparently provides an implementation of DCE/RPC over a
* named pipe (IPC$ connection using SMBtrans). details of DCE/RPC
* documentation are available (in on-line form) from the X-Open group.
*
* this module should provide a level of abstraction between SMB
* and DCE/RPC, while minimising the amount of mallocs, unnecessary
* data copies, and network traffic.
*
* in this version, which takes a "let's learn what's going on and
* get something running" approach, there is additional network
* traffic generated, but the code should be easier to understand...
*
* ... if you read the docs. or stare at packets for weeks on end.
*
*/
#include "includes.h"
/*
* A list of the rids of well known BUILTIN and Domain users
* and groups.
*/
rid_name builtin_alias_rids[] =
{
{ BUILTIN_ALIAS_RID_ADMINS , "Administrators" },
{ BUILTIN_ALIAS_RID_USERS , "Users" },
{ BUILTIN_ALIAS_RID_GUESTS , "Guests" },
{ BUILTIN_ALIAS_RID_POWER_USERS , "Power Users" },
{ BUILTIN_ALIAS_RID_ACCOUNT_OPS , "Account Operators" },
{ BUILTIN_ALIAS_RID_SYSTEM_OPS , "System Operators" },
{ BUILTIN_ALIAS_RID_PRINT_OPS , "Print Operators" },
{ BUILTIN_ALIAS_RID_BACKUP_OPS , "Backup Operators" },
{ BUILTIN_ALIAS_RID_REPLICATOR , "Replicator" },
{ 0 , NULL }
};
/* array lookup of well-known Domain RID users. */
rid_name domain_user_rids[] =
{
{ DOMAIN_USER_RID_ADMIN , "Administrator" },
{ DOMAIN_USER_RID_GUEST , "Guest" },
{ 0 , NULL }
};
/* array lookup of well-known Domain RID groups. */
rid_name domain_group_rids[] =
{
{ DOMAIN_GROUP_RID_ADMINS , "Domain Admins" },
{ DOMAIN_GROUP_RID_USERS , "Domain Users" },
{ DOMAIN_GROUP_RID_GUESTS , "Domain Guests" },
{ 0 , NULL }
};
int make_dom_gids(TALLOC_CTX *ctx, char *gids_str, DOM_GID **ppgids)
{
char *ptr;
pstring s2;
int count;
DOM_GID *gids;
*ppgids = NULL;
DEBUG(4,("make_dom_gids: %s\n", gids_str));
if (gids_str == NULL || *gids_str == 0)
return 0;
for (count = 0, ptr = gids_str;
next_token(&ptr, s2, NULL, sizeof(s2));
count++)
;
gids = (DOM_GID *)talloc(ctx, sizeof(DOM_GID) * count );
if(!gids)
{
DEBUG(0,("make_dom_gids: talloc fail !\n"));
return 0;
}
for (count = 0, ptr = gids_str;
next_token(&ptr, s2, NULL, sizeof(s2)) &&
count < LSA_MAX_GROUPS;
count++)
{
/* the entries are of the form GID/ATTR, ATTR being optional.*/
char *attr;
uint32 rid = 0;
int i;
attr = strchr_m(s2,'/');
if (attr)
*attr++ = 0;
if (!attr || !*attr)
attr = "7"; /* default value for attribute is 7 */
/* look up the RID string and see if we can turn it into a rid number */
for (i = 0; builtin_alias_rids[i].name != NULL; i++)
{
if (strequal(builtin_alias_rids[i].name, s2))
{
rid = builtin_alias_rids[i].rid;
break;
}
}
if (rid == 0)
rid = atoi(s2);
if (rid == 0)
{
DEBUG(1,("make_dom_gids: unknown well-known alias RID %s/%s\n", s2, attr));
count--;
}
else
{
gids[count].g_rid = rid;
gids[count].attr = atoi(attr);
DEBUG(5,("group id: %d attr: %d\n", gids[count].g_rid, gids[count].attr));
}
}
*ppgids = gids;
return count;
}
/*******************************************************************
gets a domain user's groups
********************************************************************/
BOOL new_get_domain_user_groups(TALLOC_CTX *ctx, int *numgroups, DOM_GID **pgids, SAM_ACCOUNT *sam_pass)
{
GROUP_MAP *map=NULL;
int i, num, num_entries, cur_gid=0;
struct group *grp;
DOM_GID *gids;
fstring user_name;
uint32 grid;
uint32 tmp_rid;
fstrcpy(user_name, pdb_get_username(sam_pass));
grid=pdb_get_group_rid(sam_pass);
DEBUG(10,("new_get_domain_user_groups: searching domain groups [%s] is a member of\n", user_name));
/* first get the list of the domain groups */
if (!enum_group_mapping(SID_NAME_DOM_GRP, &map, &num_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV))
return False;
DEBUG(10,("new_get_domain_user_groups: there are %d mapped groups\n", num_entries));
/*
* alloc memory. In the worse case, we alloc memory for nothing.
* but I prefer to alloc for nothing
* than reallocing everytime.
*/
gids = (DOM_GID *)talloc(ctx, sizeof(DOM_GID) * num_entries);
/* for each group, check if the user is a member of*/
for(i=0; i<num_entries; i++) {
if ((grp=getgrgid(map[i].gid)) == NULL) {
/* very weird !!! */
DEBUG(5,("new_get_domain_user_groups: gid %d doesn't exist anymore !\n", (int)map[i].gid));
continue;
}
for(num=0; grp->gr_mem[num]!=NULL; num++) {
if(strcmp(grp->gr_mem[num], user_name)==0) {
/* we found the user, add the group to the list */
sid_peek_rid(&map[i].sid, &(gids[cur_gid].g_rid));
gids[cur_gid].attr=map[i].sid_name_use;
DEBUG(10,("new_get_domain_user_groups: user found in group %s\n", map[i].nt_name));
cur_gid++;
break;
}
}
}
/* we have checked the groups */
/* we must now check the gid of the user or the primary group rid, that's the same */
for (i=0; i<cur_gid && grid!=gids[i].g_rid; i++)
;
/* the user's gid is already there */
if (i!=cur_gid) {
goto done;
}
for(i=0; i<num_entries; i++) {
sid_peek_rid(&map[i].sid, &tmp_rid);
if (tmp_rid==grid) {
gids[cur_gid].g_rid=tmp_rid;
gids[cur_gid].attr=map[i].sid_name_use;
DEBUG(10,("new_get_domain_user_groups: primary gid of user found in group %s\n", map[i].nt_name));
cur_gid++;
goto done; /* leave the loop early */
}
}
done:
*pgids=gids;
*numgroups=cur_gid;
safe_free(map);
}
/*******************************************************************
gets a domain user's groups
********************************************************************/
void get_domain_user_groups(char *domain_groups, const char *user)
{
pstring tmp;
if (domain_groups == NULL || user == NULL) return;
/* can only be a user or a guest. cannot be guest _and_ admin */
if (user_in_list(user, lp_domain_guest_group()))
{
slprintf(tmp, sizeof(tmp) - 1, " %ld/7 ", DOMAIN_GROUP_RID_GUESTS);
pstrcat(domain_groups, tmp);
DEBUG(3,("domain guest group access %s granted\n", tmp));
}
else
{
slprintf(tmp, sizeof(tmp) -1, " %ld/7 ", DOMAIN_GROUP_RID_USERS);
pstrcat(domain_groups, tmp);
DEBUG(3,("domain group access %s granted\n", tmp));
if (user_in_list(user, lp_domain_admin_group()))
{
slprintf(tmp, sizeof(tmp) - 1, " %ld/7 ", DOMAIN_GROUP_RID_ADMINS);
pstrcat(domain_groups, tmp);
DEBUG(3,("domain admin group access %s granted\n", tmp));
}
}
}
/*******************************************************************
Look up a local (domain) rid and return a name and type.
********************************************************************/
NTSTATUS local_lookup_group_name(uint32 rid, char *group_name, uint32 *type)
{
int i = 0;
(*type) = SID_NAME_DOM_GRP;
DEBUG(5,("lookup_group_name: rid: %d", rid));
while (domain_group_rids[i].rid != rid && domain_group_rids[i].rid != 0)
{
i++;
}
if (domain_group_rids[i].rid != 0)
{
fstrcpy(group_name, domain_group_rids[i].name);
DEBUG(5,(" = %s\n", group_name));
return NT_STATUS_OK;
}
DEBUG(5,(" none mapped\n"));
return NT_STATUS_NONE_MAPPED;
}
/*******************************************************************
Look up a local alias rid and return a name and type.
********************************************************************/
NTSTATUS local_lookup_alias_name(uint32 rid, char *alias_name, uint32 *type)
{
int i = 0;
(*type) = SID_NAME_WKN_GRP;
DEBUG(5,("lookup_alias_name: rid: %d", rid));
while (builtin_alias_rids[i].rid != rid && builtin_alias_rids[i].rid != 0)
{
i++;
}
if (builtin_alias_rids[i].rid != 0)
{
fstrcpy(alias_name, builtin_alias_rids[i].name);
DEBUG(5,(" = %s\n", alias_name));
return NT_STATUS_OK;
}
DEBUG(5,(" none mapped\n"));
return NT_STATUS_NONE_MAPPED;
}
/*******************************************************************
Look up a local user rid and return a name and type.
********************************************************************/
NTSTATUS local_lookup_user_name(uint32 rid, char *user_name, uint32 *type)
{
SAM_ACCOUNT *sampwd=NULL;
int i = 0;
BOOL ret;
(*type) = SID_NAME_USER;
DEBUG(5,("lookup_user_name: rid: %d", rid));
/* look up the well-known domain user rids first */
while (domain_user_rids[i].rid != rid && domain_user_rids[i].rid != 0)
{
i++;
}
if (domain_user_rids[i].rid != 0) {
fstrcpy(user_name, domain_user_rids[i].name);
DEBUG(5,(" = %s\n", user_name));
return NT_STATUS_OK;
}
pdb_init_sam(&sampwd);
/* ok, it's a user. find the user account */
become_root();
ret = pdb_getsampwrid(sampwd, rid);
unbecome_root();
if (ret == True) {
fstrcpy(user_name, pdb_get_username(sampwd) );
DEBUG(5,(" = %s\n", user_name));
Fix up a number of intertwined issues: The big one is a global change to allow us to NULLify the free'ed pointer to a former passdb object. This was done to allow idra's SAFE_FREE() macro to do its magic, and to satisfy the input test in pdb_init_sam() for a NULL pointer to start with. This NULL pointer test was what was breaking the adding of accounts up until now, and this code has been reworked to avoid duplicating work - I hope this will avoid a similar mess-up in future. Finally, I fixed a few nasty bugs where the pdb_ fuctions's return codes were being ignored. Some of these functions malloc() and are permitted to fail. Also, this caught a nasty bug where pdb_set_lanman_password(sam, NULL) acheived precisely didilly-squat, just returning False. Now that we check the returns this bug was spotted. This could allow different LM and NT passwords. - the pdbedit code needs to start checking these too, but I havn't had a chance to fix it. I have also fixed up where some of the password changing code was using the pdb_set functions to store *internal* data. I assume this is from a previous lot of mass conversion work... Most likally (and going on past experience) I have missed somthing, probably in the LanMan password change code which I havn't yet been able to test, but this lot is in much better shape than it was before. If all this is too much to swallow (particularly for 2.2.2) then just adding a sam_pass = NULL to the particular line of passdb.c should do the trick for the ovbious bug. Andrew Bartlett (This used to be commit 762c8758a7869809d89b4da9c2a5249678942930)
2001-09-29 17:08:26 +04:00
pdb_free_sam(&sampwd);
return NT_STATUS_OK;
}
DEBUG(5,(" none mapped\n"));
Fix up a number of intertwined issues: The big one is a global change to allow us to NULLify the free'ed pointer to a former passdb object. This was done to allow idra's SAFE_FREE() macro to do its magic, and to satisfy the input test in pdb_init_sam() for a NULL pointer to start with. This NULL pointer test was what was breaking the adding of accounts up until now, and this code has been reworked to avoid duplicating work - I hope this will avoid a similar mess-up in future. Finally, I fixed a few nasty bugs where the pdb_ fuctions's return codes were being ignored. Some of these functions malloc() and are permitted to fail. Also, this caught a nasty bug where pdb_set_lanman_password(sam, NULL) acheived precisely didilly-squat, just returning False. Now that we check the returns this bug was spotted. This could allow different LM and NT passwords. - the pdbedit code needs to start checking these too, but I havn't had a chance to fix it. I have also fixed up where some of the password changing code was using the pdb_set functions to store *internal* data. I assume this is from a previous lot of mass conversion work... Most likally (and going on past experience) I have missed somthing, probably in the LanMan password change code which I havn't yet been able to test, but this lot is in much better shape than it was before. If all this is too much to swallow (particularly for 2.2.2) then just adding a sam_pass = NULL to the particular line of passdb.c should do the trick for the ovbious bug. Andrew Bartlett (This used to be commit 762c8758a7869809d89b4da9c2a5249678942930)
2001-09-29 17:08:26 +04:00
pdb_free_sam(&sampwd);
return NT_STATUS_NONE_MAPPED;
}
/*******************************************************************
Look up a local (domain) group name and return a rid
********************************************************************/
NTSTATUS local_lookup_group_rid(char *group_name, uint32 *rid)
{
char *grp_name;
int i = -1; /* start do loop at -1 */
do /* find, if it exists, a group rid for the group name*/
{
i++;
(*rid) = domain_group_rids[i].rid;
grp_name = domain_group_rids[i].name;
} while (grp_name != NULL && !strequal(grp_name, group_name));
return (grp_name != NULL) ? NT_STATUS_OK : NT_STATUS_NONE_MAPPED;
}
/*******************************************************************
Look up a local (BUILTIN) alias name and return a rid
********************************************************************/
NTSTATUS local_lookup_alias_rid(char *alias_name, uint32 *rid)
{
char *als_name;
int i = -1; /* start do loop at -1 */
do /* find, if it exists, a alias rid for the alias name*/
{
i++;
(*rid) = builtin_alias_rids[i].rid;
als_name = builtin_alias_rids[i].name;
} while (als_name != NULL && !strequal(als_name, alias_name));
return (als_name != NULL) ? NT_STATUS_OK : NT_STATUS_NONE_MAPPED;
}
/*******************************************************************
Look up a local user name and return a rid
********************************************************************/
NTSTATUS local_lookup_user_rid(char *user_name, uint32 *rid)
{
SAM_ACCOUNT *sampass=NULL;
BOOL ret;
(*rid) = 0;
pdb_init_sam(&sampass);
/* find the user account */
become_root();
ret = pdb_getsampwnam(sampass, user_name);
unbecome_root();
if (ret == True) {
(*rid) = pdb_get_user_rid(sampass);
Fix up a number of intertwined issues: The big one is a global change to allow us to NULLify the free'ed pointer to a former passdb object. This was done to allow idra's SAFE_FREE() macro to do its magic, and to satisfy the input test in pdb_init_sam() for a NULL pointer to start with. This NULL pointer test was what was breaking the adding of accounts up until now, and this code has been reworked to avoid duplicating work - I hope this will avoid a similar mess-up in future. Finally, I fixed a few nasty bugs where the pdb_ fuctions's return codes were being ignored. Some of these functions malloc() and are permitted to fail. Also, this caught a nasty bug where pdb_set_lanman_password(sam, NULL) acheived precisely didilly-squat, just returning False. Now that we check the returns this bug was spotted. This could allow different LM and NT passwords. - the pdbedit code needs to start checking these too, but I havn't had a chance to fix it. I have also fixed up where some of the password changing code was using the pdb_set functions to store *internal* data. I assume this is from a previous lot of mass conversion work... Most likally (and going on past experience) I have missed somthing, probably in the LanMan password change code which I havn't yet been able to test, but this lot is in much better shape than it was before. If all this is too much to swallow (particularly for 2.2.2) then just adding a sam_pass = NULL to the particular line of passdb.c should do the trick for the ovbious bug. Andrew Bartlett (This used to be commit 762c8758a7869809d89b4da9c2a5249678942930)
2001-09-29 17:08:26 +04:00
pdb_free_sam(&sampass);
return NT_STATUS_OK;
}
Fix up a number of intertwined issues: The big one is a global change to allow us to NULLify the free'ed pointer to a former passdb object. This was done to allow idra's SAFE_FREE() macro to do its magic, and to satisfy the input test in pdb_init_sam() for a NULL pointer to start with. This NULL pointer test was what was breaking the adding of accounts up until now, and this code has been reworked to avoid duplicating work - I hope this will avoid a similar mess-up in future. Finally, I fixed a few nasty bugs where the pdb_ fuctions's return codes were being ignored. Some of these functions malloc() and are permitted to fail. Also, this caught a nasty bug where pdb_set_lanman_password(sam, NULL) acheived precisely didilly-squat, just returning False. Now that we check the returns this bug was spotted. This could allow different LM and NT passwords. - the pdbedit code needs to start checking these too, but I havn't had a chance to fix it. I have also fixed up where some of the password changing code was using the pdb_set functions to store *internal* data. I assume this is from a previous lot of mass conversion work... Most likally (and going on past experience) I have missed somthing, probably in the LanMan password change code which I havn't yet been able to test, but this lot is in much better shape than it was before. If all this is too much to swallow (particularly for 2.2.2) then just adding a sam_pass = NULL to the particular line of passdb.c should do the trick for the ovbious bug. Andrew Bartlett (This used to be commit 762c8758a7869809d89b4da9c2a5249678942930)
2001-09-29 17:08:26 +04:00
pdb_free_sam(&sampass);
return NT_STATUS_NONE_MAPPED;
}