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 73553 : _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 73553 : unsigned int i, num_sids = 0;
62 :
63 : const char *filter;
64 :
65 73553 : struct dom_sid *sids = NULL;
66 : const struct dom_sid *anonymous_sid, *system_sid;
67 :
68 73553 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
69 73553 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
70 :
71 73553 : session_info = talloc_zero(tmp_ctx, struct auth_session_info);
72 73553 : if (session_info == NULL) {
73 0 : TALLOC_FREE(tmp_ctx);
74 0 : return NT_STATUS_NO_MEMORY;
75 : }
76 :
77 73553 : session_info->info = talloc_reference(session_info, user_info_dc->info);
78 :
79 73553 : session_info->torture = talloc_zero(session_info, struct auth_user_info_torture);
80 73553 : if (session_info->torture == NULL) {
81 0 : TALLOC_FREE(tmp_ctx);
82 0 : return NT_STATUS_NO_MEMORY;
83 : }
84 73553 : session_info->torture->num_dc_sids = user_info_dc->num_sids;
85 73553 : session_info->torture->dc_sids = talloc_reference(session_info, user_info_dc->sids);
86 73553 : 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 73553 : session_info->session_key = data_blob_talloc(session_info, user_info_dc->user_session_key.data, user_info_dc->user_session_key.length);
94 73553 : 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 73553 : anonymous_sid = dom_sid_parse_talloc(tmp_ctx, SID_NT_ANONYMOUS);
102 73553 : if (anonymous_sid == NULL) {
103 0 : TALLOC_FREE(tmp_ctx);
104 0 : return NT_STATUS_NO_MEMORY;
105 : }
106 :
107 73553 : system_sid = dom_sid_parse_talloc(tmp_ctx, SID_NT_SYSTEM);
108 73553 : if (system_sid == NULL) {
109 0 : TALLOC_FREE(tmp_ctx);
110 0 : return NT_STATUS_NO_MEMORY;
111 : }
112 :
113 73553 : sids = talloc_array(tmp_ctx, struct dom_sid, user_info_dc->num_sids);
114 73553 : if (sids == NULL) {
115 0 : TALLOC_FREE(tmp_ctx);
116 0 : return NT_STATUS_NO_MEMORY;
117 : }
118 :
119 73553 : num_sids = user_info_dc->num_sids;
120 :
121 334613 : for (i=0; i < user_info_dc->num_sids; i++) {
122 261060 : 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 73553 : if (session_info_flags & AUTH_SESSION_INFO_DEFAULT_GROUPS) {
132 36867 : sids = talloc_realloc(tmp_ctx, sids, struct dom_sid, num_sids + 2);
133 36867 : if (sids == NULL) {
134 0 : TALLOC_FREE(tmp_ctx);
135 0 : return NT_STATUS_NO_MEMORY;
136 : }
137 :
138 36867 : sid_copy(&sids[num_sids], &global_sid_World);
139 36867 : num_sids++;
140 :
141 36867 : sid_copy(&sids[num_sids], &global_sid_Network);
142 36867 : num_sids++;
143 : }
144 :
145 73553 : if (session_info_flags & AUTH_SESSION_INFO_AUTHENTICATED) {
146 36914 : sids = talloc_realloc(tmp_ctx, sids, struct dom_sid, num_sids + 1);
147 36914 : if (sids == NULL) {
148 0 : TALLOC_FREE(tmp_ctx);
149 0 : return NT_STATUS_NO_MEMORY;
150 : }
151 :
152 36914 : sid_copy(&sids[num_sids], &global_sid_Authenticated_Users);
153 36914 : num_sids++;
154 : }
155 :
156 73553 : if (session_info_flags & AUTH_SESSION_INFO_NTLM) {
157 8001 : sids = talloc_realloc(tmp_ctx, sids, struct dom_sid, num_sids + 1);
158 8001 : if (sids == NULL) {
159 0 : TALLOC_FREE(tmp_ctx);
160 0 : return NT_STATUS_NO_MEMORY;
161 : }
162 :
163 8001 : 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 8001 : num_sids++;
168 : }
169 :
170 :
171 73553 : 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 41883 : } 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 36474 : } else if (sam_ctx) {
176 33875 : 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 772127 : 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 722080 : sid_dn = talloc_asprintf(
186 : tmp_ctx,
187 : "<SID=%s>",
188 415940 : dom_sid_str_buf(&sids[i], &buf));
189 415940 : if (sid_dn == NULL) {
190 0 : TALLOC_FREE(tmp_ctx);
191 0 : return NT_STATUS_NO_MEMORY;
192 : }
193 415940 : 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 415940 : nt_status = dsdb_expand_nested_groups(sam_ctx, &sid_blob, true, filter,
202 : tmp_ctx, &sids, &num_sids);
203 415940 : if (!NT_STATUS_IS_OK(nt_status)) {
204 0 : talloc_free(tmp_ctx);
205 0 : return nt_status;
206 : }
207 : }
208 : }
209 :
210 73553 : 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 73553 : if (!NT_STATUS_IS_OK(nt_status)) {
217 0 : TALLOC_FREE(tmp_ctx);
218 0 : return nt_status;
219 : }
220 :
221 73553 : session_info->unique_session_token = GUID_random();
222 :
223 73553 : session_info->credentials = NULL;
224 :
225 73553 : talloc_steal(mem_ctx, session_info);
226 73553 : *_session_info = session_info;
227 73553 : talloc_free(tmp_ctx);
228 73553 : return NT_STATUS_OK;
229 : }
230 :
231 :
232 : /* Fill out the auth_session_info with a cli_credentials based on the
233 : * auth_session_info we were forwarded over named pipe forwarding.
234 : *
235 : * NOTE: The stucture members of session_info_transport are stolen
236 : * with talloc_move() into auth_session_info for long term use
237 : */
238 7018 : struct auth_session_info *auth_session_info_from_transport(TALLOC_CTX *mem_ctx,
239 : struct auth_session_info_transport *session_info_transport,
240 : struct loadparm_context *lp_ctx,
241 : const char **reason)
242 : {
243 : struct auth_session_info *session_info;
244 7018 : session_info = talloc_steal(mem_ctx, session_info_transport->session_info);
245 : /*
246 : * This is to allow us to check the type of this pointer using
247 : * talloc_get_type()
248 : */
249 7018 : talloc_set_name(session_info, "struct auth_session_info");
250 : #ifdef HAVE_GSS_IMPORT_CRED
251 7018 : if (session_info_transport->exported_gssapi_credentials.length) {
252 : struct cli_credentials *creds;
253 : OM_uint32 minor_status;
254 : gss_buffer_desc cred_token;
255 : gss_cred_id_t cred_handle;
256 : const char *error_string;
257 : int ret;
258 : bool ok;
259 :
260 1155 : DEBUG(10, ("Delegated credentials supplied by client\n"));
261 :
262 1155 : cred_token.value = session_info_transport->exported_gssapi_credentials.data;
263 1155 : cred_token.length = session_info_transport->exported_gssapi_credentials.length;
264 :
265 1155 : ret = gss_import_cred(&minor_status,
266 : &cred_token,
267 : &cred_handle);
268 1155 : if (ret != GSS_S_COMPLETE) {
269 0 : *reason = "Internal error in gss_import_cred()";
270 0 : return NULL;
271 : }
272 :
273 1155 : creds = cli_credentials_init(session_info);
274 1155 : if (!creds) {
275 0 : *reason = "Out of memory in cli_credentials_init()";
276 0 : return NULL;
277 : }
278 1155 : session_info->credentials = creds;
279 :
280 1155 : ok = cli_credentials_set_conf(creds, lp_ctx);
281 1155 : if (!ok) {
282 0 : *reason = "Failed to load smb.conf";
283 0 : return NULL;
284 : }
285 :
286 : /* Just so we don't segfault trying to get at a username */
287 1155 : cli_credentials_set_anonymous(creds);
288 :
289 1155 : ret = cli_credentials_set_client_gss_creds(creds,
290 : lp_ctx,
291 : cred_handle,
292 : CRED_SPECIFIED,
293 : &error_string);
294 1155 : if (ret) {
295 0 : *reason = talloc_asprintf(mem_ctx,
296 : "Failed to set pipe forwarded"
297 : "creds: %s\n", error_string);
298 0 : return NULL;
299 : }
300 :
301 : /* This credential handle isn't useful for password
302 : * authentication, so ensure nobody tries to do that */
303 1155 : cli_credentials_set_kerberos_state(creds,
304 : CRED_USE_KERBEROS_REQUIRED,
305 : CRED_SPECIFIED);
306 :
307 : }
308 : #endif
309 6388 : return session_info;
310 : }
311 :
312 :
313 : /* Create a auth_session_info_transport from an auth_session_info.
314 : *
315 : * NOTE: Members of the auth_session_info_transport structure are
316 : * talloc_referenced() into this structure, and should not be changed.
317 : */
318 1439 : NTSTATUS auth_session_info_transport_from_session(TALLOC_CTX *mem_ctx,
319 : struct auth_session_info *session_info,
320 : struct tevent_context *event_ctx,
321 : struct loadparm_context *lp_ctx,
322 : struct auth_session_info_transport **transport_out)
323 : {
324 :
325 996 : struct auth_session_info_transport *session_info_transport
326 443 : = talloc_zero(mem_ctx, struct auth_session_info_transport);
327 1439 : if (!session_info_transport) {
328 0 : return NT_STATUS_NO_MEMORY;
329 : };
330 1439 : session_info_transport->session_info = talloc_reference(session_info_transport, session_info);
331 1439 : if (!session_info_transport->session_info) {
332 0 : return NT_STATUS_NO_MEMORY;
333 : };
334 : #ifdef HAVE_GSS_EXPORT_CRED
335 1439 : if (session_info->credentials) {
336 : struct gssapi_creds_container *gcc;
337 : OM_uint32 gret;
338 : OM_uint32 minor_status;
339 : gss_buffer_desc cred_token;
340 : const char *error_string;
341 : int ret;
342 :
343 1305 : ret = cli_credentials_get_client_gss_creds(session_info->credentials,
344 : event_ctx,
345 : lp_ctx,
346 : &gcc, &error_string);
347 1305 : if (ret != 0) {
348 0 : *transport_out = session_info_transport;
349 0 : return NT_STATUS_OK;
350 : }
351 :
352 1305 : gret = gss_export_cred(&minor_status,
353 1305 : gcc->creds,
354 : &cred_token);
355 1305 : if (gret != GSS_S_COMPLETE) {
356 0 : return NT_STATUS_INTERNAL_ERROR;
357 : }
358 :
359 1305 : if (cred_token.length) {
360 : session_info_transport->exported_gssapi_credentials
361 1305 : = data_blob_talloc(session_info_transport,
362 : cred_token.value,
363 : cred_token.length);
364 1305 : gss_release_buffer(&minor_status, &cred_token);
365 1305 : NT_STATUS_HAVE_NO_MEMORY(session_info_transport->exported_gssapi_credentials.data);
366 : }
367 : }
368 : #endif
369 1439 : *transport_out = session_info_transport;
370 1439 : return NT_STATUS_OK;
371 : }
372 :
373 :
374 : /* Produce a session_info for an arbitary DN or principal in the local
375 : * DB, assuming the local DB holds all the groups
376 : *
377 : * Supply either a principal or a DN
378 : */
379 158 : NTSTATUS authsam_get_session_info_principal(TALLOC_CTX *mem_ctx,
380 : struct loadparm_context *lp_ctx,
381 : struct ldb_context *sam_ctx,
382 : const char *principal,
383 : struct ldb_dn *user_dn,
384 : uint32_t session_info_flags,
385 : struct auth_session_info **session_info)
386 : {
387 : NTSTATUS nt_status;
388 : struct auth_user_info_dc *user_info_dc;
389 158 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
390 158 : if (!tmp_ctx) {
391 0 : return NT_STATUS_NO_MEMORY;
392 : }
393 158 : nt_status = authsam_get_user_info_dc_principal(tmp_ctx, lp_ctx, sam_ctx,
394 : principal, user_dn,
395 : &user_info_dc);
396 158 : if (!NT_STATUS_IS_OK(nt_status)) {
397 0 : talloc_free(tmp_ctx);
398 0 : return nt_status;
399 : }
400 :
401 158 : nt_status = auth_generate_session_info(tmp_ctx, lp_ctx, sam_ctx,
402 : user_info_dc, session_info_flags,
403 : session_info);
404 :
405 158 : if (NT_STATUS_IS_OK(nt_status)) {
406 158 : talloc_steal(mem_ctx, *session_info);
407 : }
408 158 : talloc_free(tmp_ctx);
409 158 : return nt_status;
410 : }
411 :
412 : /**
413 : * prints a struct auth_session_info security token to debug output.
414 : */
415 0 : void auth_session_info_debug(int dbg_lev,
416 : const struct auth_session_info *session_info)
417 : {
418 0 : if (!session_info) {
419 0 : DEBUG(dbg_lev, ("Session Info: (NULL)\n"));
420 0 : return;
421 : }
422 :
423 0 : security_token_debug(DBGC_AUTH, dbg_lev,
424 0 : session_info->security_token);
425 : }
|