Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Authentication utility functions
4 : Copyright (C) Andrew Tridgell 1992-1998
5 : Copyright (C) Andrew Bartlett 2001-2010
6 : Copyright (C) Jeremy Allison 2000-2001
7 : Copyright (C) Rafal Szczesniak 2002
8 : Copyright (C) Stefan Metzmacher 2005
9 :
10 : This program is free software; you can redistribute it and/or modify
11 : it under the terms of the GNU General Public License as published by
12 : the Free Software Foundation; either version 3 of the License, or
13 : (at your option) any later version.
14 :
15 : This program is distributed in the hope that it will be useful,
16 : but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : GNU General Public License for more details.
19 :
20 : You should have received a copy of the GNU General Public License
21 : along with this program. If not, see <http://www.gnu.org/licenses/>.
22 : */
23 :
24 : #include "includes.h"
25 : #include "auth/auth.h"
26 : #include "auth/auth_sam.h"
27 : #include "auth/credentials/credentials.h"
28 : #include "auth/credentials/credentials_krb5.h"
29 : #include "libcli/security/security.h"
30 : #include "libcli/auth/libcli_auth.h"
31 : #include "dsdb/samdb/samdb.h"
32 : #include "auth/session_proto.h"
33 : #include "system/kerberos.h"
34 : #include <gssapi/gssapi.h>
35 : #include "libcli/wbclient/wbclient.h"
36 :
37 : #undef DBGC_CLASS
38 : #define DBGC_CLASS DBGC_AUTH
39 :
40 7 : _PUBLIC_ struct auth_session_info *anonymous_session(TALLOC_CTX *mem_ctx,
41 : struct loadparm_context *lp_ctx)
42 : {
43 : NTSTATUS nt_status;
44 7 : struct auth_session_info *session_info = NULL;
45 7 : nt_status = auth_anonymous_session_info(mem_ctx, lp_ctx, &session_info);
46 7 : if (!NT_STATUS_IS_OK(nt_status)) {
47 0 : return NULL;
48 : }
49 7 : return session_info;
50 : }
51 :
52 69408 : _PUBLIC_ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx,
53 : struct loadparm_context *lp_ctx, /* Optional, if you don't want privilages */
54 : struct ldb_context *sam_ctx, /* Optional, if you don't want local groups */
55 : struct auth_user_info_dc *user_info_dc,
56 : uint32_t session_info_flags,
57 : struct auth_session_info **_session_info)
58 : {
59 : struct auth_session_info *session_info;
60 : NTSTATUS nt_status;
61 69408 : unsigned int i, num_sids = 0;
62 :
63 : const char *filter;
64 :
65 69408 : struct dom_sid *sids = NULL;
66 : const struct dom_sid *anonymous_sid, *system_sid;
67 :
68 69408 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
69 69408 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
70 :
71 69408 : session_info = talloc_zero(tmp_ctx, struct auth_session_info);
72 69408 : if (session_info == NULL) {
73 0 : TALLOC_FREE(tmp_ctx);
74 0 : return NT_STATUS_NO_MEMORY;
75 : }
76 :
77 69408 : session_info->info = talloc_reference(session_info, user_info_dc->info);
78 :
79 69408 : session_info->torture = talloc_zero(session_info, struct auth_user_info_torture);
80 69408 : if (session_info->torture == NULL) {
81 0 : TALLOC_FREE(tmp_ctx);
82 0 : return NT_STATUS_NO_MEMORY;
83 : }
84 69408 : session_info->torture->num_dc_sids = user_info_dc->num_sids;
85 69408 : session_info->torture->dc_sids = talloc_reference(session_info, user_info_dc->sids);
86 69408 : if (session_info->torture->dc_sids == NULL) {
87 0 : TALLOC_FREE(tmp_ctx);
88 0 : return NT_STATUS_NO_MEMORY;
89 : }
90 :
91 : /* unless set otherwise, the session key is the user session
92 : * key from the auth subsystem */
93 69408 : session_info->session_key = data_blob_talloc(session_info, user_info_dc->user_session_key.data, user_info_dc->user_session_key.length);
94 69408 : if (!session_info->session_key.data && session_info->session_key.length) {
95 0 : if (session_info->session_key.data == NULL) {
96 0 : TALLOC_FREE(tmp_ctx);
97 0 : return NT_STATUS_NO_MEMORY;
98 : }
99 : }
100 :
101 69408 : anonymous_sid = dom_sid_parse_talloc(tmp_ctx, SID_NT_ANONYMOUS);
102 69408 : if (anonymous_sid == NULL) {
103 0 : TALLOC_FREE(tmp_ctx);
104 0 : return NT_STATUS_NO_MEMORY;
105 : }
106 :
107 69408 : system_sid = dom_sid_parse_talloc(tmp_ctx, SID_NT_SYSTEM);
108 69408 : if (system_sid == NULL) {
109 0 : TALLOC_FREE(tmp_ctx);
110 0 : return NT_STATUS_NO_MEMORY;
111 : }
112 :
113 69408 : sids = talloc_array(tmp_ctx, struct dom_sid, user_info_dc->num_sids);
114 69408 : if (sids == NULL) {
115 0 : TALLOC_FREE(tmp_ctx);
116 0 : return NT_STATUS_NO_MEMORY;
117 : }
118 :
119 69408 : num_sids = user_info_dc->num_sids;
120 :
121 320057 : for (i=0; i < user_info_dc->num_sids; i++) {
122 250649 : sids[i] = user_info_dc->sids[i];
123 : }
124 :
125 : /*
126 : * Finally add the "standard" sids.
127 : * The only difference between guest and "anonymous"
128 : * is the addition of Authenticated_Users.
129 : */
130 :
131 69408 : if (session_info_flags & AUTH_SESSION_INFO_DEFAULT_GROUPS) {
132 32703 : sids = talloc_realloc(tmp_ctx, sids, struct dom_sid, num_sids + 2);
133 32703 : if (sids == NULL) {
134 0 : TALLOC_FREE(tmp_ctx);
135 0 : return NT_STATUS_NO_MEMORY;
136 : }
137 :
138 32703 : sid_copy(&sids[num_sids], &global_sid_World);
139 32703 : num_sids++;
140 :
141 32703 : sid_copy(&sids[num_sids], &global_sid_Network);
142 32703 : num_sids++;
143 : }
144 :
145 69408 : if (session_info_flags & AUTH_SESSION_INFO_AUTHENTICATED) {
146 32786 : sids = talloc_realloc(tmp_ctx, sids, struct dom_sid, num_sids + 1);
147 32786 : if (sids == NULL) {
148 0 : TALLOC_FREE(tmp_ctx);
149 0 : return NT_STATUS_NO_MEMORY;
150 : }
151 :
152 32786 : sid_copy(&sids[num_sids], &global_sid_Authenticated_Users);
153 32786 : num_sids++;
154 : }
155 :
156 69408 : if (session_info_flags & AUTH_SESSION_INFO_NTLM) {
157 8883 : sids = talloc_realloc(tmp_ctx, sids, struct dom_sid, num_sids + 1);
158 8883 : if (sids == NULL) {
159 0 : TALLOC_FREE(tmp_ctx);
160 0 : return NT_STATUS_NO_MEMORY;
161 : }
162 :
163 8883 : if (!dom_sid_parse(SID_NT_NTLM_AUTHENTICATION, &sids[num_sids])) {
164 0 : TALLOC_FREE(tmp_ctx);
165 0 : return NT_STATUS_INTERNAL_ERROR;
166 : }
167 8883 : num_sids++;
168 : }
169 :
170 :
171 69408 : if (num_sids > PRIMARY_USER_SID_INDEX && dom_sid_equal(anonymous_sid, &sids[PRIMARY_USER_SID_INDEX])) {
172 : /* Don't expand nested groups of system, anonymous etc*/
173 36880 : } else if (num_sids > PRIMARY_USER_SID_INDEX && dom_sid_equal(system_sid, &sids[PRIMARY_USER_SID_INDEX])) {
174 : /* Don't expand nested groups of system, anonymous etc*/
175 32470 : } else if (sam_ctx) {
176 30845 : filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))",
177 : GROUP_TYPE_BUILTIN_LOCAL_GROUP);
178 :
179 : /* Search for each group in the token */
180 757076 : for (i = 0; i < num_sids; i++) {
181 : struct dom_sid_buf buf;
182 : const char *sid_dn;
183 : DATA_BLOB sid_blob;
184 :
185 701852 : sid_dn = talloc_asprintf(
186 : tmp_ctx,
187 : "<SID=%s>",
188 391271 : dom_sid_str_buf(&sids[i], &buf));
189 391271 : if (sid_dn == NULL) {
190 0 : TALLOC_FREE(tmp_ctx);
191 0 : return NT_STATUS_NO_MEMORY;
192 : }
193 391271 : sid_blob = data_blob_string_const(sid_dn);
194 :
195 : /* This function takes in memberOf values and expands
196 : * them, as long as they meet the filter - so only
197 : * builtin groups
198 : *
199 : * We already have the SID in the token, so set
200 : * 'only childs' flag to true */
201 391271 : nt_status = dsdb_expand_nested_groups(sam_ctx, &sid_blob, true, filter,
202 : tmp_ctx, &sids, &num_sids);
203 391271 : if (!NT_STATUS_IS_OK(nt_status)) {
204 0 : talloc_free(tmp_ctx);
205 0 : return nt_status;
206 : }
207 : }
208 : }
209 :
210 69408 : nt_status = security_token_create(session_info,
211 : lp_ctx,
212 : num_sids,
213 : sids,
214 : session_info_flags,
215 : &session_info->security_token);
216 69408 : if (!NT_STATUS_IS_OK(nt_status)) {
217 0 : TALLOC_FREE(tmp_ctx);
218 0 : return nt_status;
219 : }
220 :
221 69408 : session_info->unique_session_token = GUID_random();
222 :
223 69408 : session_info->credentials = NULL;
224 :
225 69408 : session_info->ticket_type = user_info_dc->ticket_type;
226 :
227 69408 : talloc_steal(mem_ctx, session_info);
228 69408 : *_session_info = session_info;
229 69408 : talloc_free(tmp_ctx);
230 69408 : return NT_STATUS_OK;
231 : }
232 :
233 :
234 : /* Fill out the auth_session_info with a cli_credentials based on the
235 : * auth_session_info we were forwarded over named pipe forwarding.
236 : *
237 : * NOTE: The stucture members of session_info_transport are stolen
238 : * with talloc_move() into auth_session_info for long term use
239 : */
240 4923 : struct auth_session_info *auth_session_info_from_transport(TALLOC_CTX *mem_ctx,
241 : struct auth_session_info_transport *session_info_transport,
242 : struct loadparm_context *lp_ctx,
243 : const char **reason)
244 : {
245 : struct auth_session_info *session_info;
246 4923 : session_info = talloc_steal(mem_ctx, session_info_transport->session_info);
247 : /*
248 : * This is to allow us to check the type of this pointer using
249 : * talloc_get_type()
250 : */
251 4923 : talloc_set_name(session_info, "struct auth_session_info");
252 : #ifdef HAVE_GSS_IMPORT_CRED
253 4923 : if (session_info_transport->exported_gssapi_credentials.length) {
254 : struct cli_credentials *creds;
255 : OM_uint32 minor_status;
256 : gss_buffer_desc cred_token;
257 : gss_cred_id_t cred_handle;
258 : const char *error_string;
259 : int ret;
260 : bool ok;
261 :
262 1103 : DEBUG(10, ("Delegated credentials supplied by client\n"));
263 :
264 1103 : cred_token.value = session_info_transport->exported_gssapi_credentials.data;
265 1103 : cred_token.length = session_info_transport->exported_gssapi_credentials.length;
266 :
267 1103 : ret = gss_import_cred(&minor_status,
268 : &cred_token,
269 : &cred_handle);
270 1103 : if (ret != GSS_S_COMPLETE) {
271 0 : *reason = "Internal error in gss_import_cred()";
272 0 : return NULL;
273 : }
274 :
275 1103 : creds = cli_credentials_init(session_info);
276 1103 : if (!creds) {
277 0 : *reason = "Out of memory in cli_credentials_init()";
278 0 : return NULL;
279 : }
280 1103 : session_info->credentials = creds;
281 :
282 1103 : ok = cli_credentials_set_conf(creds, lp_ctx);
283 1103 : if (!ok) {
284 0 : *reason = "Failed to load smb.conf";
285 0 : return NULL;
286 : }
287 :
288 : /* Just so we don't segfault trying to get at a username */
289 1103 : cli_credentials_set_anonymous(creds);
290 :
291 1103 : ret = cli_credentials_set_client_gss_creds(creds,
292 : lp_ctx,
293 : cred_handle,
294 : CRED_SPECIFIED,
295 : &error_string);
296 1103 : if (ret) {
297 0 : *reason = talloc_asprintf(mem_ctx,
298 : "Failed to set pipe forwarded"
299 : "creds: %s\n", error_string);
300 0 : return NULL;
301 : }
302 :
303 : /* This credential handle isn't useful for password
304 : * authentication, so ensure nobody tries to do that */
305 1103 : cli_credentials_set_kerberos_state(creds,
306 : CRED_USE_KERBEROS_REQUIRED,
307 : CRED_SPECIFIED);
308 :
309 : }
310 : #endif
311 4923 : return session_info;
312 : }
313 :
314 :
315 : /* Create a auth_session_info_transport from an auth_session_info.
316 : *
317 : * NOTE: Members of the auth_session_info_transport structure are
318 : * talloc_referenced() into this structure, and should not be changed.
319 : */
320 1390 : NTSTATUS auth_session_info_transport_from_session(TALLOC_CTX *mem_ctx,
321 : struct auth_session_info *session_info,
322 : struct tevent_context *event_ctx,
323 : struct loadparm_context *lp_ctx,
324 : struct auth_session_info_transport **transport_out)
325 : {
326 :
327 950 : struct auth_session_info_transport *session_info_transport
328 440 : = talloc_zero(mem_ctx, struct auth_session_info_transport);
329 1390 : if (!session_info_transport) {
330 0 : return NT_STATUS_NO_MEMORY;
331 : };
332 1390 : session_info_transport->session_info = talloc_reference(session_info_transport, session_info);
333 1390 : if (!session_info_transport->session_info) {
334 0 : return NT_STATUS_NO_MEMORY;
335 : };
336 : #ifdef HAVE_GSS_EXPORT_CRED
337 1390 : if (session_info->credentials) {
338 : struct gssapi_creds_container *gcc;
339 : OM_uint32 gret;
340 : OM_uint32 minor_status;
341 : gss_buffer_desc cred_token;
342 : const char *error_string;
343 : int ret;
344 :
345 1256 : ret = cli_credentials_get_client_gss_creds(session_info->credentials,
346 : event_ctx,
347 : lp_ctx,
348 : &gcc, &error_string);
349 1256 : if (ret != 0) {
350 0 : *transport_out = session_info_transport;
351 0 : return NT_STATUS_OK;
352 : }
353 :
354 1256 : gret = gss_export_cred(&minor_status,
355 1256 : gcc->creds,
356 : &cred_token);
357 1256 : if (gret != GSS_S_COMPLETE) {
358 0 : return NT_STATUS_INTERNAL_ERROR;
359 : }
360 :
361 1256 : if (cred_token.length) {
362 : session_info_transport->exported_gssapi_credentials
363 1256 : = data_blob_talloc(session_info_transport,
364 : cred_token.value,
365 : cred_token.length);
366 1256 : gss_release_buffer(&minor_status, &cred_token);
367 1256 : NT_STATUS_HAVE_NO_MEMORY(session_info_transport->exported_gssapi_credentials.data);
368 : }
369 : }
370 : #endif
371 1390 : *transport_out = session_info_transport;
372 1390 : return NT_STATUS_OK;
373 : }
374 :
375 :
376 : /* Produce a session_info for an arbitary DN or principal in the local
377 : * DB, assuming the local DB holds all the groups
378 : *
379 : * Supply either a principal or a DN
380 : */
381 159 : NTSTATUS authsam_get_session_info_principal(TALLOC_CTX *mem_ctx,
382 : struct loadparm_context *lp_ctx,
383 : struct ldb_context *sam_ctx,
384 : const char *principal,
385 : struct ldb_dn *user_dn,
386 : uint32_t session_info_flags,
387 : struct auth_session_info **session_info)
388 : {
389 : NTSTATUS nt_status;
390 : struct auth_user_info_dc *user_info_dc;
391 159 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
392 159 : if (!tmp_ctx) {
393 0 : return NT_STATUS_NO_MEMORY;
394 : }
395 159 : nt_status = authsam_get_user_info_dc_principal(tmp_ctx, lp_ctx, sam_ctx,
396 : principal, user_dn,
397 : &user_info_dc);
398 159 : if (!NT_STATUS_IS_OK(nt_status)) {
399 0 : talloc_free(tmp_ctx);
400 0 : return nt_status;
401 : }
402 :
403 159 : nt_status = auth_generate_session_info(tmp_ctx, lp_ctx, sam_ctx,
404 : user_info_dc, session_info_flags,
405 : session_info);
406 :
407 159 : if (NT_STATUS_IS_OK(nt_status)) {
408 159 : talloc_steal(mem_ctx, *session_info);
409 : }
410 159 : talloc_free(tmp_ctx);
411 159 : return nt_status;
412 : }
413 :
414 : /**
415 : * prints a struct auth_session_info security token to debug output.
416 : */
417 0 : void auth_session_info_debug(int dbg_lev,
418 : const struct auth_session_info *session_info)
419 : {
420 0 : if (!session_info) {
421 0 : DEBUG(dbg_lev, ("Session Info: (NULL)\n"));
422 0 : return;
423 : }
424 :
425 0 : security_token_debug(DBGC_AUTH, dbg_lev,
426 0 : session_info->security_token);
427 : }
|