#include "includes.h"
NSS_STATUS winbindd_request(int req_type,
struct winbindd_request *request,
struct winbindd_response *response);
static BOOL parse_domain_user(char *domuser, fstring domain, fstring user)
{
char *p = strchr(domuser,*lp_winbind_separator());
if (!p)
return False;
fstrcpy(user, p+1);
fstrcpy(domain, domuser);
domain[PTR_DIFF(p, domuser)] = 0;
strupper(domain);
return True;
}
BOOL winbind_lookup_name(const char *name, DOM_SID *sid,
enum SID_NAME_USE *name_type)
{
struct winbindd_request request;
struct winbindd_response response;
NSS_STATUS result;
if (!sid || !name_type)
return False;
if (!strchr(name, *lp_winbind_separator()))
return False;
ZERO_STRUCT(request);
ZERO_STRUCT(response);
fstrcpy(request.data.name, name);
if ((result = winbindd_request(WINBINDD_LOOKUPNAME, &request,
&response)) == NSS_STATUS_SUCCESS) {
string_to_sid(sid, response.data.sid.sid);
*name_type = (enum SID_NAME_USE)response.data.sid.type;
}
return result == NSS_STATUS_SUCCESS;
}
BOOL winbind_lookup_sid(DOM_SID *sid, fstring dom_name, fstring name,
enum SID_NAME_USE *name_type)
{
struct winbindd_request request;
struct winbindd_response response;
NSS_STATUS result;
fstring sid_str;
ZERO_STRUCT(request);
ZERO_STRUCT(response);
sid_to_string(sid_str, sid);
fstrcpy(request.data.sid, sid_str);
result = winbindd_request(WINBINDD_LOOKUPSID, &request, &response);
if (result == NSS_STATUS_SUCCESS) {
parse_domain_user(response.data.name.name, dom_name, name);
*name_type = (enum SID_NAME_USE)response.data.name.type;
DEBUG(10, ("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n",
sid_str, dom_name, name));
}
return (result == NSS_STATUS_SUCCESS);
}
BOOL winbind_sid_to_uid(uid_t *puid, DOM_SID *sid)
{
struct winbindd_request request;
struct winbindd_response response;
int result;
fstring sid_str;
if (!puid)
return False;
ZERO_STRUCT(request);
ZERO_STRUCT(response);
sid_to_string(sid_str, sid);
fstrcpy(request.data.sid, sid_str);
result = winbindd_request(WINBINDD_SID_TO_UID, &request, &response);
if (result == NSS_STATUS_SUCCESS) {
*puid = response.data.uid;
}
return (result == NSS_STATUS_SUCCESS);
}
BOOL winbind_uid_to_sid(DOM_SID *sid, uid_t uid)
{
struct winbindd_request request;
struct winbindd_response response;
int result;
if (!sid)
return False;
ZERO_STRUCT(request);
ZERO_STRUCT(response);
request.data.uid = uid;
result = winbindd_request(WINBINDD_UID_TO_SID, &request, &response);
if (result == NSS_STATUS_SUCCESS) {
string_to_sid(sid, response.data.sid.sid);
} else {
sid_copy(sid, &global_sid_NULL);
}
return (result == NSS_STATUS_SUCCESS);
}
BOOL winbind_sid_to_gid(gid_t *pgid, DOM_SID *sid)
{
struct winbindd_request request;
struct winbindd_response response;
int result;
fstring sid_str;
if (!pgid)
return False;
ZERO_STRUCT(request);
ZERO_STRUCT(response);
sid_to_string(sid_str, sid);
fstrcpy(request.data.sid, sid_str);
result = winbindd_request(WINBINDD_SID_TO_GID, &request, &response);
if (result == NSS_STATUS_SUCCESS) {
*pgid = response.data.gid;
}
return (result == NSS_STATUS_SUCCESS);
}
BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
{
struct winbindd_request request;
struct winbindd_response response;
int result;
if (!sid)
return False;
ZERO_STRUCT(request);
ZERO_STRUCT(response);
request.data.gid = gid;
result = winbindd_request(WINBINDD_GID_TO_SID, &request, &response);
if (result == NSS_STATUS_SUCCESS) {
string_to_sid(sid, response.data.sid.sid);
} else {
sid_copy(sid, &global_sid_NULL);
}
return (result == NSS_STATUS_SUCCESS);
}
static int wb_getgroups(const char *user, gid_t **groups)
{
struct winbindd_request request;
struct winbindd_response response;
int result;
fstrcpy(request.data.username, user);
ZERO_STRUCT(response);
result = winbindd_request(WINBINDD_GETGROUPS, &request, &response);
if (result == NSS_STATUS_SUCCESS) {
*groups = (gid_t *)response.extra_data;
return response.data.num_entries;
}
return -1;
}
int winbind_initgroups(char *user, gid_t gid)
{
gid_t *tgr, *groups = NULL;
int result;
if (!strchr(user, *lp_winbind_separator())) {
return initgroups(user, gid);
}
result = wb_getgroups(user, &groups);
DEBUG(10,("winbind_getgroups: %s: result = %s\n", user,
result == -1 ? "FAIL" : "SUCCESS"));
if (result != -1) {
int ngroups = result, i;
BOOL is_member = False;
for (i = 0; i < ngroups; i++) {
if (groups[i] == gid) {
is_member = True;
}
}
if (!is_member) {
tgr = (gid_t *)Realloc(groups, sizeof(gid_t) * ngroups + 1);
if (!tgr) {
errno = ENOMEM;
result = -1;
goto done;
}
else groups = tgr;
groups[ngroups] = gid;
ngroups++;
}
if (sys_setgroups(ngroups, groups) == -1) {
errno = EPERM;
result = -1;
goto done;
}
} else {
errno = EIO;
}
done:
SAFE_FREE(groups);
return result;
}
int winbind_getgroups(const char *user, int size, gid_t *list)
{
gid_t *groups = NULL;
int result, i;
if (!strchr(user, *lp_winbind_separator()))
return -1;
result = wb_getgroups(user, &groups);
if (size == 0)
goto done;
if (result > size) {
result = -1;
errno = EINVAL;
goto done;
}
for (i = 0; i < result; i++) {
list[i] = groups[i];
}
done:
SAFE_FREE(groups);
return result;
}
BOOL winbind_uidtoname(fstring name, uid_t uid)
{
DOM_SID sid;
fstring dom_name;
fstring user_name;
enum SID_NAME_USE name_type;
if (!winbind_uid_to_sid(&sid, uid))
return False;
if (!winbind_lookup_sid(&sid, dom_name, user_name, &name_type))
return False;
if (name_type != SID_NAME_USER)
return False;
slprintf(name, sizeof(fstring)-1, "%s%s%s", dom_name,
lp_winbind_separator(), user_name);
return True;
}
BOOL winbind_gidtoname(fstring name, gid_t gid)
{
DOM_SID sid;
fstring dom_name;
fstring group_name;
enum SID_NAME_USE name_type;
if (!winbind_gid_to_sid(&sid, gid))
return False;
if (!winbind_lookup_sid(&sid, dom_name, group_name, &name_type))
return False;
if (name_type != SID_NAME_DOM_GRP)
return False;
slprintf(name, sizeof(fstring)-1, "%s%s%s", dom_name,
lp_winbind_separator(), group_name);
return True;
}
BOOL winbind_nametouid(uid_t *puid, const char *name)
{
DOM_SID sid;
enum SID_NAME_USE name_type;
if (!winbind_lookup_name(name, &sid, &name_type))
return False;
if (name_type != SID_NAME_USER)
return False;
return winbind_sid_to_uid(puid, &sid);
}
BOOL winbind_nametogid(gid_t *pgid, const char *gname)
{
DOM_SID g_sid;
enum SID_NAME_USE name_type;
if (!winbind_lookup_name(gname, &g_sid, &name_type))
return False;
if (name_type != SID_NAME_DOM_GRP)
return False;
return winbind_sid_to_gid(pgid, &g_sid);
}