Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Deal with unix elements in the security token
5 :
6 : Copyright (C) Andrew Tridgell 2004
7 : Copyright (C) Andrew Bartlett 2011
8 :
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.
13 :
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.
18 :
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/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "auth/auth.h"
25 : #include "libcli/wbclient/wbclient.h"
26 : #include "param/param.h"
27 :
28 : #undef DBGC_CLASS
29 : #define DBGC_CLASS DBGC_AUTH
30 :
31 : /*
32 : form a security_unix_token from the current security_token
33 : */
34 12280 : NTSTATUS security_token_to_unix_token(TALLOC_CTX *mem_ctx,
35 : struct security_token *token,
36 : struct security_unix_token **sec)
37 : {
38 893 : uint32_t s, g;
39 893 : NTSTATUS status;
40 893 : struct id_map *ids;
41 893 : bool match;
42 :
43 12280 : match = security_token_is_system(token);
44 12280 : if (match) {
45 : /*
46 : * SYSTEM user uid and gid is 0
47 : */
48 :
49 1043 : *sec = talloc_zero(mem_ctx, struct security_unix_token);
50 1043 : if (*sec == NULL) {
51 0 : return NT_STATUS_NO_MEMORY;
52 : }
53 :
54 1043 : return NT_STATUS_OK;
55 : }
56 :
57 : /* we can't do unix security without a user and group */
58 11237 : if (token->num_sids < PRIMARY_SIDS_COUNT) {
59 0 : return NT_STATUS_ACCESS_DENIED;
60 : }
61 :
62 11237 : *sec = talloc_zero(mem_ctx, struct security_unix_token);
63 11237 : if (*sec == NULL) {
64 0 : return NT_STATUS_NO_MEMORY;
65 : }
66 :
67 11237 : ids = talloc_zero_array(mem_ctx, struct id_map, token->num_sids);
68 11237 : NT_STATUS_HAVE_NO_MEMORY(ids);
69 :
70 161662 : for (s=0; s < token->num_sids; s++) {
71 150425 : ids[s].sid = &token->sids[s];
72 150425 : ids[s].status = ID_UNKNOWN;
73 : }
74 :
75 11237 : status = wbc_sids_to_xids(ids, token->num_sids);
76 11237 : NT_STATUS_NOT_OK_RETURN(status);
77 :
78 11237 : g = token->num_sids;
79 11237 : if (ids[PRIMARY_USER_SID_INDEX].xid.type != ID_TYPE_BOTH) {
80 8777 : g--;
81 : }
82 11237 : (*sec)->ngroups = g;
83 11237 : (*sec)->groups = talloc_array(*sec, gid_t, (*sec)->ngroups);
84 11237 : NT_STATUS_HAVE_NO_MEMORY((*sec)->groups);
85 :
86 11237 : g=0;
87 11237 : if (ids[PRIMARY_USER_SID_INDEX].xid.type == ID_TYPE_BOTH) {
88 2460 : (*sec)->uid = ids[0].xid.id;
89 2460 : (*sec)->groups[g] = ids[0].xid.id;
90 2460 : g++;
91 8777 : } else if (ids[PRIMARY_USER_SID_INDEX].xid.type == ID_TYPE_UID) {
92 8777 : (*sec)->uid = ids[0].xid.id;
93 : } else {
94 0 : struct dom_sid_buf buf;
95 0 : 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 0 : security_token_debug(DBGC_AUTH, 0, token);
99 0 : return NT_STATUS_INVALID_SID;
100 : }
101 :
102 11237 : if (ids[PRIMARY_GROUP_SID_INDEX].xid.type == ID_TYPE_BOTH ||
103 8112 : ids[PRIMARY_GROUP_SID_INDEX].xid.type == ID_TYPE_GID) {
104 11237 : (*sec)->gid = ids[PRIMARY_GROUP_SID_INDEX].xid.id;
105 11237 : (*sec)->groups[g] = ids[PRIMARY_GROUP_SID_INDEX].xid.id;
106 11237 : g++;
107 : } else {
108 0 : struct dom_sid_buf buf;
109 0 : 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 0 : security_token_debug(DBGC_AUTH, 0, token);
113 0 : return NT_STATUS_INVALID_SID;
114 : }
115 :
116 139188 : for (s=REMAINING_SIDS_INDEX; s < token->num_sids; s++) {
117 127951 : if (ids[s].xid.type == ID_TYPE_BOTH ||
118 0 : ids[s].xid.type == ID_TYPE_GID) {
119 127951 : (*sec)->groups[g] = ids[s].xid.id;
120 127951 : g++;
121 : } else {
122 0 : struct dom_sid_buf buf;
123 0 : 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 0 : security_token_debug(DBGC_AUTH, 0, token);
127 0 : return NT_STATUS_INVALID_SID;
128 : }
129 : }
130 :
131 11237 : DEBUG(5, ("Successfully converted security token to a unix token:"));
132 11237 : security_token_debug(0, 5, token);
133 11237 : TALLOC_FREE(ids);
134 :
135 11237 : return NT_STATUS_OK;
136 : }
137 :
138 : /*
139 : * Fill in the unix_info elements in a struct session_info
140 : */
141 11076 : NTSTATUS fill_unix_info(struct loadparm_context *lp_ctx,
142 : const char *original_user_name,
143 : struct auth_session_info *session_info)
144 : {
145 11076 : session_info->unix_info = talloc_zero(session_info,
146 : struct auth_user_info_unix);
147 11076 : NT_STATUS_HAVE_NO_MEMORY(session_info->unix_info);
148 :
149 22152 : session_info->unix_info->unix_name =
150 22152 : talloc_asprintf(session_info->unix_info,
151 11076 : "%s%s%s", session_info->info->domain_name,
152 : lpcfg_winbind_separator(lp_ctx),
153 11076 : session_info->info->account_name);
154 11076 : NT_STATUS_HAVE_NO_MEMORY(session_info->unix_info->unix_name);
155 :
156 11076 : if (original_user_name == NULL) {
157 1043 : original_user_name = session_info->unix_info->unix_name;
158 : }
159 :
160 22152 : session_info->unix_info->sanitized_username =
161 11076 : talloc_alpha_strcpy(session_info->unix_info,
162 : original_user_name,
163 : ". _-$");
164 11076 : NT_STATUS_HAVE_NO_MEMORY(session_info->unix_info->sanitized_username);
165 :
166 11076 : return NT_STATUS_OK;
167 : }
168 :
169 : /*
170 : Fill in the auth_user_info_unix and auth_unix_token elements in a struct session_info
171 : */
172 10958 : NTSTATUS auth_session_info_fill_unix(struct loadparm_context *lp_ctx,
173 : const char *original_user_name,
174 : struct auth_session_info *session_info)
175 : {
176 10958 : NTSTATUS status = NT_STATUS_OK;
177 :
178 10958 : status = security_token_to_unix_token(session_info,
179 : session_info->security_token,
180 : &session_info->unix_token);
181 10958 : if (!NT_STATUS_IS_OK(status)) {
182 0 : return status;
183 : }
184 :
185 10958 : status = fill_unix_info(lp_ctx,
186 : original_user_name,
187 : session_info);
188 10958 : if (!NT_STATUS_IS_OK(status)) {
189 0 : return status;
190 : }
191 :
192 10958 : return NT_STATUS_OK;
193 : }
194 :
195 : /*
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.
202 : */
203 118 : 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)
208 : {
209 20 : NTSTATUS status;
210 :
211 118 : session_info->unix_token = talloc_zero(session_info,
212 : struct security_unix_token);
213 118 : if (session_info->unix_token == NULL) {
214 0 : return NT_STATUS_NO_MEMORY;
215 : }
216 :
217 118 : session_info->unix_token->uid = uid;
218 118 : session_info->unix_token->gid = gid;
219 :
220 118 : status = fill_unix_info(lp_ctx,
221 : original_user_name,
222 : session_info);
223 118 : if (!NT_STATUS_IS_OK(status)) {
224 0 : return status;
225 : }
226 :
227 118 : return NT_STATUS_OK;
228 : }
|