smbd: allow directory leases in close_directory()
[samba4-gss.git] / source4 / auth / unix_token.c
blob97b8292a2dd1dc7d0ce328a2cfffadcad1861044
1 /*
2 Unix SMB/CIFS implementation.
4 Deal with unix elements in the security token
6 Copyright (C) Andrew Tridgell 2004
7 Copyright (C) Andrew Bartlett 2011
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "auth/auth.h"
25 #include "libcli/wbclient/wbclient.h"
26 #include "param/param.h"
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_AUTH
32 form a security_unix_token from the current security_token
34 NTSTATUS security_token_to_unix_token(TALLOC_CTX *mem_ctx,
35 struct security_token *token,
36 struct security_unix_token **sec)
38 uint32_t s, g;
39 NTSTATUS status;
40 struct id_map *ids;
41 bool match;
43 match = security_token_is_system(token);
44 if (match) {
46 * SYSTEM user uid and gid is 0
49 *sec = talloc_zero(mem_ctx, struct security_unix_token);
50 if (*sec == NULL) {
51 return NT_STATUS_NO_MEMORY;
54 return NT_STATUS_OK;
57 /* we can't do unix security without a user and group */
58 if (token->num_sids < PRIMARY_SIDS_COUNT) {
59 return NT_STATUS_ACCESS_DENIED;
62 *sec = talloc_zero(mem_ctx, struct security_unix_token);
63 if (*sec == NULL) {
64 return NT_STATUS_NO_MEMORY;
67 ids = talloc_zero_array(mem_ctx, struct id_map, token->num_sids);
68 NT_STATUS_HAVE_NO_MEMORY(ids);
70 for (s=0; s < token->num_sids; s++) {
71 ids[s].sid = &token->sids[s];
72 ids[s].status = ID_UNKNOWN;
75 status = wbc_sids_to_xids(ids, token->num_sids);
76 NT_STATUS_NOT_OK_RETURN(status);
78 g = token->num_sids;
79 if (ids[PRIMARY_USER_SID_INDEX].xid.type != ID_TYPE_BOTH) {
80 g--;
82 (*sec)->ngroups = g;
83 (*sec)->groups = talloc_array(*sec, gid_t, (*sec)->ngroups);
84 NT_STATUS_HAVE_NO_MEMORY((*sec)->groups);
86 g=0;
87 if (ids[PRIMARY_USER_SID_INDEX].xid.type == ID_TYPE_BOTH) {
88 (*sec)->uid = ids[0].xid.id;
89 (*sec)->groups[g] = ids[0].xid.id;
90 g++;
91 } else if (ids[PRIMARY_USER_SID_INDEX].xid.type == ID_TYPE_UID) {
92 (*sec)->uid = ids[0].xid.id;
93 } else {
94 struct dom_sid_buf buf;
95 DEBUG(0, ("Unable to convert first SID (%s) in user token to a UID. Conversion was returned as type %d, full token:\n",
96 dom_sid_str_buf(ids[PRIMARY_USER_SID_INDEX].sid, &buf),
97 (int)ids[PRIMARY_USER_SID_INDEX].xid.type));
98 security_token_debug(DBGC_AUTH, 0, token);
99 return NT_STATUS_INVALID_SID;
102 if (ids[PRIMARY_GROUP_SID_INDEX].xid.type == ID_TYPE_BOTH ||
103 ids[PRIMARY_GROUP_SID_INDEX].xid.type == ID_TYPE_GID) {
104 (*sec)->gid = ids[PRIMARY_GROUP_SID_INDEX].xid.id;
105 (*sec)->groups[g] = ids[PRIMARY_GROUP_SID_INDEX].xid.id;
106 g++;
107 } else {
108 struct dom_sid_buf buf;
109 DEBUG(0, ("Unable to convert second SID (%s) in user token to a GID. Conversion was returned as type %d, full token:\n",
110 dom_sid_str_buf(ids[PRIMARY_GROUP_SID_INDEX].sid, &buf),
111 (int)ids[PRIMARY_GROUP_SID_INDEX].xid.type));
112 security_token_debug(DBGC_AUTH, 0, token);
113 return NT_STATUS_INVALID_SID;
116 for (s=REMAINING_SIDS_INDEX; s < token->num_sids; s++) {
117 if (ids[s].xid.type == ID_TYPE_BOTH ||
118 ids[s].xid.type == ID_TYPE_GID) {
119 (*sec)->groups[g] = ids[s].xid.id;
120 g++;
121 } else {
122 struct dom_sid_buf buf;
123 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",
124 dom_sid_str_buf(ids[s].sid, &buf),
125 (unsigned int)s, (int)ids[s].xid.type));
126 security_token_debug(DBGC_AUTH, 0, token);
127 return NT_STATUS_INVALID_SID;
131 DEBUG(5, ("Successfully converted security token to a unix token:"));
132 security_token_debug(0, 5, token);
133 TALLOC_FREE(ids);
135 return NT_STATUS_OK;
139 * Fill in the unix_info elements in a struct session_info
141 NTSTATUS fill_unix_info(struct loadparm_context *lp_ctx,
142 const char *original_user_name,
143 struct auth_session_info *session_info)
145 session_info->unix_info = talloc_zero(session_info,
146 struct auth_user_info_unix);
147 NT_STATUS_HAVE_NO_MEMORY(session_info->unix_info);
149 session_info->unix_info->unix_name =
150 talloc_asprintf(session_info->unix_info,
151 "%s%s%s", session_info->info->domain_name,
152 lpcfg_winbind_separator(lp_ctx),
153 session_info->info->account_name);
154 NT_STATUS_HAVE_NO_MEMORY(session_info->unix_info->unix_name);
156 if (original_user_name == NULL) {
157 original_user_name = session_info->unix_info->unix_name;
160 session_info->unix_info->sanitized_username =
161 talloc_alpha_strcpy(session_info->unix_info,
162 original_user_name,
163 ". _-$");
164 NT_STATUS_HAVE_NO_MEMORY(session_info->unix_info->sanitized_username);
166 return NT_STATUS_OK;
170 Fill in the auth_user_info_unix and auth_unix_token elements in a struct session_info
172 NTSTATUS auth_session_info_fill_unix(struct loadparm_context *lp_ctx,
173 const char *original_user_name,
174 struct auth_session_info *session_info)
176 NTSTATUS status = NT_STATUS_OK;
178 status = security_token_to_unix_token(session_info,
179 session_info->security_token,
180 &session_info->unix_token);
181 if (!NT_STATUS_IS_OK(status)) {
182 return status;
185 status = fill_unix_info(lp_ctx,
186 original_user_name,
187 session_info);
188 if (!NT_STATUS_IS_OK(status)) {
189 return status;
192 return NT_STATUS_OK;
196 * Set the given auth_user_info_unix and auth_unix_token elements in a
197 * struct session_info, similar auth_session_info_fill_unix().
198 * Receives the uid and gid for the unix token as parameters and does
199 * not query the unix token from winbind (via security_token_to_unix_token()).
200 * This is useful to fill a user session info manually if winbind is not
201 * available.
203 NTSTATUS auth_session_info_set_unix(struct loadparm_context *lp_ctx,
204 const char *original_user_name,
205 int uid,
206 int gid,
207 struct auth_session_info *session_info)
209 NTSTATUS status;
211 session_info->unix_token = talloc_zero(session_info,
212 struct security_unix_token);
213 if (session_info->unix_token == NULL) {
214 return NT_STATUS_NO_MEMORY;
217 session_info->unix_token->uid = uid;
218 session_info->unix_token->gid = gid;
220 status = fill_unix_info(lp_ctx,
221 original_user_name,
222 session_info);
223 if (!NT_STATUS_IS_OK(status)) {
224 return status;
227 return NT_STATUS_OK;