/* form a security_unix_token from the current security_token */ NTSTATUS security_token_to_unix_token(TALLOC_CTX *mem_ctx, struct wbc_context *wbc_ctx, struct security_token *token, struct security_unix_token **sec) { uint32_t s, g; NTSTATUS status; struct id_map *ids; struct composite_context *ctx; /* we can't do unix security without a user and group */ if (token->num_sids < 2) { return NT_STATUS_ACCESS_DENIED; } *sec = talloc_zero(mem_ctx, struct security_unix_token); if (*sec == NULL) { return NT_STATUS_NO_MEMORY; } ids = talloc_zero_array(mem_ctx, struct id_map, token->num_sids); NT_STATUS_HAVE_NO_MEMORY(ids); for (s=0; s < token->num_sids; s++) { ids[s].sid = &token->sids[s]; ids[s].status = ID_UNKNOWN; } ctx = wbc_sids_to_xids_send(wbc_ctx, ids, token->num_sids, ids); NT_STATUS_HAVE_NO_MEMORY(ctx); status = wbc_sids_to_xids_recv(ctx, &ids); NT_STATUS_NOT_OK_RETURN(status); g = token->num_sids; if (ids[0].xid.type != ID_TYPE_BOTH) { g--; } (*sec)->ngroups = g; (*sec)->groups = talloc_array(*sec, gid_t, (*sec)->ngroups); NT_STATUS_HAVE_NO_MEMORY((*sec)->groups); g=0; if (ids[0].xid.type == ID_TYPE_BOTH) { (*sec)->uid = ids[0].xid.id; (*sec)->groups[g] = ids[0].xid.id; g++; } else if (ids[0].xid.type == ID_TYPE_UID) { (*sec)->uid = ids[0].xid.id; } else { char *sid_str = dom_sid_string(mem_ctx, ids[0].sid); DEBUG(0, ("Unable to convert first SID (%s) in user token to a UID. Conversion was returned as type %d, full token:\n", sid_str, (int)ids[0].xid.type)); security_token_debug(0, 0, token); talloc_free(sid_str); return NT_STATUS_INVALID_SID; } if (ids[1].xid.type == ID_TYPE_BOTH || ids[1].xid.type == ID_TYPE_GID) { (*sec)->gid = ids[1].xid.id; (*sec)->groups[g] = ids[1].xid.id; g++; } else { char *sid_str = dom_sid_string(mem_ctx, ids[1].sid); DEBUG(0, ("Unable to convert second SID (%s) in user token to a GID. Conversion was returned as type %d, full token:\n", sid_str, (int)ids[1].xid.type)); security_token_debug(0, 0, token); talloc_free(sid_str); return NT_STATUS_INVALID_SID; } for (s=2; s < token->num_sids; s++) { if (ids[s].xid.type == ID_TYPE_BOTH || ids[s].xid.type == ID_TYPE_GID) { (*sec)->groups[g] = ids[s].xid.id; g++; } else { char *sid_str = dom_sid_string(mem_ctx, ids[s].sid); DEBUG(0, ("Unable to convert SID (%s) at index %u in user token to a GID. Conversion was returned as type %d, full token:\n", sid_str, (unsigned int)s, (int)ids[s].xid.type)); security_token_debug(0, 0, token); talloc_free(sid_str); return NT_STATUS_INVALID_SID; } } DEBUG(5, ("Successfully converted security token to a unix token:")); security_token_debug(0, 5, token); TALLOC_FREE(ids); return NT_STATUS_OK; }
/* save the acl for a file into system.nfs4acl */ static NTSTATUS pvfs_acl_save_nfs4(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd, struct security_descriptor *sd) { NTSTATUS status; void *privs; struct nfs4acl acl; int i; TALLOC_CTX *tmp_ctx; struct id_map *ids; struct composite_context *ctx; tmp_ctx = talloc_new(pvfs); NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); acl.a_version = 0; acl.a_flags = sd->type; acl.a_count = sd->dacl?sd->dacl->num_aces:0; acl.a_owner_mask = 0; acl.a_group_mask = 0; acl.a_other_mask = 0; acl.ace = talloc_array(tmp_ctx, struct nfs4ace, acl.a_count); if (!acl.ace) { talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } ids = talloc_array(tmp_ctx, struct id_map, acl.a_count); if (ids == NULL) { talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } for (i=0;i<acl.a_count;i++) { struct security_ace *ace = &sd->dacl->aces[i]; ZERO_STRUCT(ids[i].xid); ids[i].sid = dom_sid_dup(ids, &ace->trustee); if (ids[i].sid == NULL) { talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } ids[i].status = ID_UNKNOWN; } ctx = wbc_sids_to_xids_send(pvfs->wbc_ctx,ids, acl.a_count, ids); if (ctx == NULL) { talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } status = wbc_sids_to_xids_recv(ctx, &ids); if (!NT_STATUS_IS_OK(status)) { talloc_free(tmp_ctx); return status; } for (i=0;i<acl.a_count;i++) { struct nfs4ace *a = &acl.ace[i]; struct security_ace *ace = &sd->dacl->aces[i]; a->e_type = ace->type; a->e_flags = ace->flags; a->e_mask = ace->access_mask; if (ids[i].xid.type != ID_TYPE_UID) { a->e_flags |= ACE4_IDENTIFIER_GROUP; } a->e_id = ids[i].xid.id; a->e_who = ""; } privs = root_privileges(); status = pvfs_xattr_ndr_save(pvfs, name->full_name, fd, NFS4ACL_XATTR_NAME, &acl, (void *) ndr_push_nfs4acl); talloc_free(privs); talloc_free(tmp_ctx); return status; }
/* form a security_unix_token from the current security_token */ NTSTATUS security_token_to_unix_token(TALLOC_CTX *mem_ctx, struct wbc_context *wbc_ctx, struct security_token *token, struct security_unix_token **sec) { int i; NTSTATUS status; struct id_map *ids; struct composite_context *ctx; *sec = talloc(mem_ctx, struct security_unix_token); /* we can't do unix security without a user and group */ if (token->num_sids < 2) { return NT_STATUS_ACCESS_DENIED; } ids = talloc_array(mem_ctx, struct id_map, token->num_sids); NT_STATUS_HAVE_NO_MEMORY(ids); (*sec)->ngroups = token->num_sids - 2; (*sec)->groups = talloc_array(*sec, gid_t, (*sec)->ngroups); NT_STATUS_HAVE_NO_MEMORY((*sec)->groups); for (i=0;i<token->num_sids;i++) { ZERO_STRUCT(ids[i].xid); ids[i].sid = &token->sids[i]; ids[i].status = ID_UNKNOWN; } ctx = wbc_sids_to_xids_send(wbc_ctx, ids, token->num_sids, ids); NT_STATUS_HAVE_NO_MEMORY(ctx); status = wbc_sids_to_xids_recv(ctx, &ids); NT_STATUS_NOT_OK_RETURN(status); if (ids[0].xid.type == ID_TYPE_BOTH || ids[0].xid.type == ID_TYPE_UID) { (*sec)->uid = ids[0].xid.id; } else { return NT_STATUS_INVALID_SID; } if (ids[1].xid.type == ID_TYPE_BOTH || ids[1].xid.type == ID_TYPE_GID) { (*sec)->gid = ids[1].xid.id; } else { return NT_STATUS_INVALID_SID; } for (i=0;i<(*sec)->ngroups;i++) { if (ids[i+2].xid.type == ID_TYPE_BOTH || ids[i+2].xid.type == ID_TYPE_GID) { (*sec)->groups[i] = ids[i+2].xid.id; } else { return NT_STATUS_INVALID_SID; } } TALLOC_FREE(ids); return NT_STATUS_OK; }