/src/samba/source4/auth/unix_token.c
Line | Count | Source |
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 | 0 | #define DBGC_CLASS DBGC_AUTH |
30 | | |
31 | | /* |
32 | | form a security_unix_token from the current security_token |
33 | | */ |
34 | | NTSTATUS security_token_to_unix_token(TALLOC_CTX *mem_ctx, |
35 | | struct security_token *token, |
36 | | struct security_unix_token **sec) |
37 | 0 | { |
38 | 0 | uint32_t s, g; |
39 | 0 | NTSTATUS status; |
40 | 0 | struct id_map *ids; |
41 | 0 | bool match; |
42 | |
|
43 | 0 | match = security_token_is_system(token); |
44 | 0 | if (match) { |
45 | | /* |
46 | | * SYSTEM user uid and gid is 0 |
47 | | */ |
48 | |
|
49 | 0 | *sec = talloc_zero(mem_ctx, struct security_unix_token); |
50 | 0 | if (*sec == NULL) { |
51 | 0 | return NT_STATUS_NO_MEMORY; |
52 | 0 | } |
53 | | |
54 | 0 | return NT_STATUS_OK; |
55 | 0 | } |
56 | | |
57 | | /* we can't do unix security without a user and group */ |
58 | 0 | if (token->num_sids < PRIMARY_SIDS_COUNT) { |
59 | 0 | return NT_STATUS_ACCESS_DENIED; |
60 | 0 | } |
61 | | |
62 | 0 | *sec = talloc_zero(mem_ctx, struct security_unix_token); |
63 | 0 | if (*sec == NULL) { |
64 | 0 | return NT_STATUS_NO_MEMORY; |
65 | 0 | } |
66 | | |
67 | 0 | ids = talloc_zero_array(mem_ctx, struct id_map, token->num_sids); |
68 | 0 | NT_STATUS_HAVE_NO_MEMORY(ids); |
69 | | |
70 | 0 | for (s=0; s < token->num_sids; s++) { |
71 | 0 | ids[s].sid = &token->sids[s]; |
72 | 0 | ids[s].status = ID_UNKNOWN; |
73 | 0 | } |
74 | |
|
75 | 0 | status = wbc_sids_to_xids(ids, token->num_sids); |
76 | 0 | NT_STATUS_NOT_OK_RETURN(status); |
77 | | |
78 | 0 | g = token->num_sids; |
79 | 0 | if (ids[PRIMARY_USER_SID_INDEX].xid.type != ID_TYPE_BOTH) { |
80 | 0 | g--; |
81 | 0 | } |
82 | 0 | (*sec)->ngroups = g; |
83 | 0 | (*sec)->groups = talloc_array(*sec, gid_t, (*sec)->ngroups); |
84 | 0 | NT_STATUS_HAVE_NO_MEMORY((*sec)->groups); |
85 | | |
86 | 0 | g=0; |
87 | 0 | if (ids[PRIMARY_USER_SID_INDEX].xid.type == ID_TYPE_BOTH) { |
88 | 0 | (*sec)->uid = ids[0].xid.id; |
89 | 0 | (*sec)->groups[g] = ids[0].xid.id; |
90 | 0 | g++; |
91 | 0 | } else if (ids[PRIMARY_USER_SID_INDEX].xid.type == ID_TYPE_UID) { |
92 | 0 | (*sec)->uid = ids[0].xid.id; |
93 | 0 | } 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 | 0 | dom_sid_str_buf(ids[PRIMARY_USER_SID_INDEX].sid, &buf), |
97 | 0 | (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 | 0 | } |
101 | | |
102 | 0 | if (ids[PRIMARY_GROUP_SID_INDEX].xid.type == ID_TYPE_BOTH || |
103 | 0 | ids[PRIMARY_GROUP_SID_INDEX].xid.type == ID_TYPE_GID) { |
104 | 0 | (*sec)->gid = ids[PRIMARY_GROUP_SID_INDEX].xid.id; |
105 | 0 | (*sec)->groups[g] = ids[PRIMARY_GROUP_SID_INDEX].xid.id; |
106 | 0 | g++; |
107 | 0 | } 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 | 0 | dom_sid_str_buf(ids[PRIMARY_GROUP_SID_INDEX].sid, &buf), |
111 | 0 | (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 | 0 | } |
115 | | |
116 | 0 | for (s=REMAINING_SIDS_INDEX; s < token->num_sids; s++) { |
117 | 0 | if (ids[s].xid.type == ID_TYPE_BOTH || |
118 | 0 | ids[s].xid.type == ID_TYPE_GID) { |
119 | 0 | (*sec)->groups[g] = ids[s].xid.id; |
120 | 0 | g++; |
121 | 0 | } 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 | 0 | dom_sid_str_buf(ids[s].sid, &buf), |
125 | 0 | (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 | 0 | } |
129 | 0 | } |
130 | | |
131 | 0 | DEBUG(5, ("Successfully converted security token to a unix token:")); |
132 | 0 | security_token_debug(0, 5, token); |
133 | 0 | TALLOC_FREE(ids); |
134 | |
|
135 | 0 | return NT_STATUS_OK; |
136 | 0 | } |
137 | | |
138 | | /* |
139 | | * Fill in the unix_info elements in a struct session_info |
140 | | */ |
141 | | NTSTATUS fill_unix_info(struct loadparm_context *lp_ctx, |
142 | | const char *original_user_name, |
143 | | struct auth_session_info *session_info) |
144 | 0 | { |
145 | 0 | session_info->unix_info = talloc_zero(session_info, |
146 | 0 | struct auth_user_info_unix); |
147 | 0 | NT_STATUS_HAVE_NO_MEMORY(session_info->unix_info); |
148 | | |
149 | 0 | session_info->unix_info->unix_name = |
150 | 0 | talloc_asprintf(session_info->unix_info, |
151 | 0 | "%s%s%s", session_info->info->domain_name, |
152 | 0 | lpcfg_winbind_separator(lp_ctx), |
153 | 0 | session_info->info->account_name); |
154 | 0 | NT_STATUS_HAVE_NO_MEMORY(session_info->unix_info->unix_name); |
155 | | |
156 | 0 | if (original_user_name == NULL) { |
157 | 0 | original_user_name = session_info->unix_info->unix_name; |
158 | 0 | } |
159 | |
|
160 | 0 | session_info->unix_info->sanitized_username = |
161 | 0 | talloc_alpha_strcpy(session_info->unix_info, |
162 | 0 | original_user_name, |
163 | 0 | ". _-$"); |
164 | 0 | NT_STATUS_HAVE_NO_MEMORY(session_info->unix_info->sanitized_username); |
165 | | |
166 | 0 | return NT_STATUS_OK; |
167 | 0 | } |
168 | | |
169 | | /* |
170 | | Fill in the auth_user_info_unix and auth_unix_token elements in a struct session_info |
171 | | */ |
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) |
175 | 0 | { |
176 | 0 | NTSTATUS status = NT_STATUS_OK; |
177 | |
|
178 | 0 | status = security_token_to_unix_token(session_info, |
179 | 0 | session_info->security_token, |
180 | 0 | &session_info->unix_token); |
181 | 0 | if (!NT_STATUS_IS_OK(status)) { |
182 | 0 | return status; |
183 | 0 | } |
184 | | |
185 | 0 | status = fill_unix_info(lp_ctx, |
186 | 0 | original_user_name, |
187 | 0 | session_info); |
188 | 0 | if (!NT_STATUS_IS_OK(status)) { |
189 | 0 | return status; |
190 | 0 | } |
191 | | |
192 | 0 | return NT_STATUS_OK; |
193 | 0 | } |
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 | | 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 | 0 | { |
209 | 0 | NTSTATUS status; |
210 | |
|
211 | 0 | session_info->unix_token = talloc_zero(session_info, |
212 | 0 | struct security_unix_token); |
213 | 0 | if (session_info->unix_token == NULL) { |
214 | 0 | return NT_STATUS_NO_MEMORY; |
215 | 0 | } |
216 | | |
217 | 0 | session_info->unix_token->uid = uid; |
218 | 0 | session_info->unix_token->gid = gid; |
219 | |
|
220 | 0 | status = fill_unix_info(lp_ctx, |
221 | 0 | original_user_name, |
222 | 0 | session_info); |
223 | 0 | if (!NT_STATUS_IS_OK(status)) { |
224 | 0 | return status; |
225 | 0 | } |
226 | | |
227 | 0 | return NT_STATUS_OK; |
228 | 0 | } |