Copyright (C) Andrew Tridgell 2000
This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
+ modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
+ version 3 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
/* Call winbindd to convert a name to a sid */
-BOOL winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid,
- enum SID_NAME_USE *name_type)
+bool winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid,
+ enum lsa_SidType *name_type)
{
struct winbindd_request request;
struct winbindd_response response;
&response)) == NSS_STATUS_SUCCESS) {
if (!string_to_sid(sid, response.data.sid.sid))
return False;
- *name_type = (enum SID_NAME_USE)response.data.sid.type;
+ *name_type = (enum lsa_SidType)response.data.sid.type;
}
return result == NSS_STATUS_SUCCESS;
/* Call winbindd to convert sid to name */
-BOOL winbind_lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
+bool winbind_lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
const char **domain, const char **name,
- enum SID_NAME_USE *name_type)
+ enum lsa_SidType *name_type)
{
struct winbindd_request request;
struct winbindd_response response;
}
}
- *name_type = (enum SID_NAME_USE)response.data.name.type;
+ *name_type = (enum lsa_SidType)response.data.name.type;
DEBUG(10, ("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n",
- sid_string_static(sid), *domain, *name));
+ sid_string_static(sid), response.data.name.dom_name,
+ response.data.name.name));
return True;
}
+bool winbind_lookup_rids(TALLOC_CTX *mem_ctx,
+ const DOM_SID *domain_sid,
+ int num_rids, uint32 *rids,
+ const char **domain_name,
+ const char ***names, enum lsa_SidType **types)
+{
+ size_t i, buflen;
+ ssize_t len;
+ char *ridlist;
+ char *p;
+ struct winbindd_request request;
+ struct winbindd_response response;
+ NSS_STATUS result;
+
+ if (num_rids == 0) {
+ return False;
+ }
+
+ /* Initialise request */
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ fstrcpy(request.data.sid, sid_string_static(domain_sid));
+
+ len = 0;
+ buflen = 0;
+ ridlist = NULL;
+
+ for (i=0; i<num_rids; i++) {
+ sprintf_append(mem_ctx, &ridlist, &len, &buflen,
+ "%ld\n", rids[i]);
+ }
+
+ if (ridlist == NULL) {
+ return False;
+ }
+
+ request.extra_data.data = ridlist;
+ request.extra_len = strlen(ridlist)+1;
+
+ result = winbindd_request_response(WINBINDD_LOOKUPRIDS,
+ &request, &response);
+
+ TALLOC_FREE(ridlist);
+
+ if (result != NSS_STATUS_SUCCESS) {
+ return False;
+ }
+
+ *domain_name = talloc_strdup(mem_ctx, response.data.domain_name);
+
+ *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids);
+ *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
+
+ if ((*names == NULL) || (*types == NULL)) {
+ goto fail;
+ }
+
+ p = (char *)response.extra_data.data;
+
+ for (i=0; i<num_rids; i++) {
+ char *q;
+
+ if (*p == '\0') {
+ DEBUG(10, ("Got invalid reply: %s\n",
+ (char *)response.extra_data.data));
+ goto fail;
+ }
+
+ (*types)[i] = (enum lsa_SidType)strtoul(p, &q, 10);
+
+ if (*q != ' ') {
+ DEBUG(10, ("Got invalid reply: %s\n",
+ (char *)response.extra_data.data));
+ goto fail;
+ }
+
+ p = q+1;
+
+ q = strchr(p, '\n');
+ if (q == NULL) {
+ DEBUG(10, ("Got invalid reply: %s\n",
+ (char *)response.extra_data.data));
+ goto fail;
+ }
+
+ *q = '\0';
+
+ (*names)[i] = talloc_strdup(*names, p);
+
+ p = q+1;
+ }
+
+ if (*p != '\0') {
+ DEBUG(10, ("Got invalid reply: %s\n",
+ (char *)response.extra_data.data));
+ goto fail;
+ }
+
+ SAFE_FREE(response.extra_data.data);
+
+ return True;
+
+ fail:
+ TALLOC_FREE(*names);
+ TALLOC_FREE(*types);
+ return False;
+}
+
/* Call winbindd to convert SID to uid */
-BOOL winbind_sid_to_uid(uid_t *puid, const DOM_SID *sid)
+bool winbind_sid_to_uid(uid_t *puid, const DOM_SID *sid)
{
struct winbindd_request request;
struct winbindd_response response;
/* Call winbindd to convert uid to sid */
-BOOL winbind_uid_to_sid(DOM_SID *sid, uid_t uid)
+bool winbind_uid_to_sid(DOM_SID *sid, uid_t uid)
{
struct winbindd_request request;
struct winbindd_response response;
/* Call winbindd to convert SID to gid */
-BOOL winbind_sid_to_gid(gid_t *pgid, const DOM_SID *sid)
+bool winbind_sid_to_gid(gid_t *pgid, const DOM_SID *sid)
{
struct winbindd_request request;
struct winbindd_response response;
/* Call winbindd to convert gid to sid */
-BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
+bool winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
{
struct winbindd_request request;
struct winbindd_response response;
return (result == NSS_STATUS_SUCCESS);
}
-BOOL winbind_allocate_rid(uint32 *rid)
+/* Call winbindd to convert SID to uid */
+
+bool winbind_sids_to_unixids(struct id_map *ids, int num_ids)
{
struct winbindd_request request;
struct winbindd_response response;
int result;
+ DOM_SID *sids;
+ int i;
/* Initialise request */
ZERO_STRUCT(request);
ZERO_STRUCT(response);
- /* Make request */
+ request.extra_len = num_ids * sizeof(DOM_SID);
- result = winbindd_request_response(WINBINDD_ALLOCATE_RID, &request, &response);
+ sids = (DOM_SID *)SMB_MALLOC(request.extra_len);
+ for (i = 0; i < num_ids; i++) {
+ sid_copy(&sids[i], ids[i].sid);
+ }
- if (result != NSS_STATUS_SUCCESS)
- return False;
+ request.extra_data.data = (char *)sids;
+
+ /* Make request */
+
+ result = winbindd_request_response(WINBINDD_SIDS_TO_XIDS, &request, &response);
/* Copy out result */
- *rid = response.data.rid;
- return True;
+ if (result == NSS_STATUS_SUCCESS) {
+ struct unixid *wid = (struct unixid *)response.extra_data.data;
+
+ for (i = 0; i < num_ids; i++) {
+ if (wid[i].type == -1) {
+ ids[i].status = ID_UNMAPPED;
+ } else {
+ ids[i].status = ID_MAPPED;
+ ids[i].xid.type = wid[i].type;
+ ids[i].xid.id = wid[i].id;
+ }
+ }
+ }
+
+ SAFE_FREE(request.extra_data.data);
+ SAFE_FREE(response.extra_data.data);
+
+ return (result == NSS_STATUS_SUCCESS);
+}
+
+bool winbind_idmap_dump_maps(TALLOC_CTX *memctx, const char *file)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ int result;
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ request.extra_data.data = SMB_STRDUP(file);
+ request.extra_len = strlen(request.extra_data.data) + 1;
+
+ result = winbindd_request_response(WINBINDD_DUMP_MAPS, &request, &response);
+
+ SAFE_FREE(request.extra_data.data);
+ return (result == NSS_STATUS_SUCCESS);
}
-BOOL winbind_allocate_rid_and_gid(uint32 *rid, gid_t *gid)
+bool winbind_allocate_uid(uid_t *uid)
{
struct winbindd_request request;
struct winbindd_response response;
/* Make request */
- result = winbindd_request_response(WINBINDD_ALLOCATE_RID_AND_GID, &request,
- &response);
+ result = winbindd_request_response(WINBINDD_ALLOCATE_UID,
+ &request, &response);
if (result != NSS_STATUS_SUCCESS)
return False;
/* Copy out result */
- *rid = response.data.rid_and_gid.rid;
- *gid = response.data.rid_and_gid.gid;
+ *uid = response.data.uid;
return True;
}
-/* Fetch the list of groups a user is a member of from winbindd. This is
- used by winbind_getgroups. */
-
-static int wb_getgroups(const char *user, gid_t **groups)
+bool winbind_allocate_gid(gid_t *gid)
{
struct winbindd_request request;
struct winbindd_response response;
int result;
- /* Call winbindd */
+ /* Initialise request */
ZERO_STRUCT(request);
- fstrcpy(request.data.username, user);
-
ZERO_STRUCT(response);
- result = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response);
+ /* Make request */
- if (result == NSS_STATUS_SUCCESS) {
-
- /* Return group list. Don't forget to free the group list
- when finished. */
+ result = winbindd_request_response(WINBINDD_ALLOCATE_GID,
+ &request, &response);
- *groups = (gid_t *)response.extra_data;
- return response.data.num_entries;
- }
+ if (result != NSS_STATUS_SUCCESS)
+ return False;
- return -1;
-}
+ /* Copy out result */
+ *gid = response.data.gid;
-/* Call winbindd to initialise group membership. This is necessary for
- some systems (i.e RH5.2) that do not have an initgroups function as part
- of the nss extension. In RH5.2 this is implemented using getgrent()
- which can be amazingly inefficient as well as having problems with
- username case. */
+ return True;
+}
-int winbind_initgroups(char *user, gid_t gid)
+bool winbind_set_mapping(const struct id_map *map)
{
- gid_t *tgr, *groups = NULL;
+ struct winbindd_request request;
+ struct winbindd_response response;
int result;
- /* Call normal initgroups if we are a local user */
-
- if (!strchr(user, *lp_winbind_separator())) {
- return initgroups(user, gid);
- }
-
- result = wb_getgroups(user, &groups);
+ /* Initialise request */
- DEBUG(10,("winbind_getgroups: %s: result = %s\n", user,
- result == -1 ? "FAIL" : "SUCCESS"));
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
- if (result != -1) {
- int ngroups = result, i;
- BOOL is_member = False;
+ /* Make request */
- /* Check to see if the passed gid is already in the list */
+ request.data.dual_idmapset.id = map->xid.id;
+ request.data.dual_idmapset.type = map->xid.type;
+ sid_to_string(request.data.dual_idmapset.sid, map->sid);
- for (i = 0; i < ngroups; i++) {
- if (groups[i] == gid) {
- is_member = True;
- }
- }
+ result = winbindd_request_response(WINBINDD_SET_MAPPING, &request, &response);
- /* Add group to list if necessary */
+ return (result == NSS_STATUS_SUCCESS);
+}
- if (!is_member) {
- tgr = SMB_REALLOC_ARRAY(groups, gid_t, ngroups + 1);
-
- if (!tgr) {
- errno = ENOMEM;
- result = -1;
- goto done;
- }
- else groups = tgr;
+bool winbind_set_uid_hwm(unsigned long id)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ int result;
- groups[ngroups] = gid;
- ngroups++;
- }
+ /* Initialise request */
- /* Set the groups */
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
- if (sys_setgroups(ngroups, groups) == -1) {
- errno = EPERM;
- result = -1;
- goto done;
- }
+ /* Make request */
- } else {
-
- /* The call failed. Set errno to something so we don't get
- a bogus value from the last failed system call. */
+ request.data.dual_idmapset.id = id;
+ request.data.dual_idmapset.type = ID_TYPE_UID;
- errno = EIO;
- }
+ result = winbindd_request_response(WINBINDD_SET_HWM, &request, &response);
- /* Free response data if necessary */
+ return (result == NSS_STATUS_SUCCESS);
+}
- done:
- SAFE_FREE(groups);
+bool winbind_set_gid_hwm(unsigned long id)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ int result;
- return result;
-}
+ /* Initialise request */
-/* Return a list of groups the user is a member of. This function is
- useful for large systems where inverting the group database would be too
- time consuming. If size is zero, list is not modified and the total
- number of groups for the user is returned. */
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
-int winbind_getgroups(const char *user, gid_t **list)
-{
- /*
- * Don't do the lookup if the name has no separator _and_ we are not in
- * 'winbind use default domain' mode.
- */
+ /* Make request */
- if (!(strchr(user, *lp_winbind_separator()) || lp_winbind_use_default_domain()))
- return -1;
+ request.data.dual_idmapset.id = id;
+ request.data.dual_idmapset.type = ID_TYPE_GID;
- /* Fetch list of groups */
+ result = winbindd_request_response(WINBINDD_SET_HWM, &request, &response);
- return wb_getgroups(user, list);
+ return (result == NSS_STATUS_SUCCESS);
}
/**********************************************************************
simple wrapper function to see if winbindd is alive
**********************************************************************/
-BOOL winbind_ping( void )
+bool winbind_ping( void )
{
NSS_STATUS result;