78171957272990d573de87d5f90eefe5a637bbb4
[sfrench/samba-autobuild/.git] / source4 / auth / session.c
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 "libcli/security/security.h"
27 #include "libcli/auth/libcli_auth.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "auth/credentials/credentials.h"
30 #include "param/param.h"
31 #include "auth/session_proto.h"
32
33 _PUBLIC_ struct auth_session_info *anonymous_session(TALLOC_CTX *mem_ctx, 
34                                             struct loadparm_context *lp_ctx) 
35 {
36         NTSTATUS nt_status;
37         struct auth_session_info *session_info = NULL;
38         nt_status = auth_anonymous_session_info(mem_ctx, lp_ctx, &session_info);
39         if (!NT_STATUS_IS_OK(nt_status)) {
40                 return NULL;
41         }
42         return session_info;
43 }
44
45 _PUBLIC_ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx,
46                                              struct auth_context *auth_context,
47                                              struct auth_serversupplied_info *server_info,
48                                              struct auth_session_info **_session_info)
49 {
50         struct auth_session_info *session_info;
51         NTSTATUS nt_status;
52         unsigned int i, num_groupSIDs = 0;
53         const char *account_sid_string;
54         const char *account_sid_dn;
55         DATA_BLOB account_sid_blob;
56         const char *primary_group_string;
57         const char *primary_group_dn;
58         DATA_BLOB primary_group_blob;
59
60         const char *filter;
61
62         struct dom_sid **groupSIDs = NULL;
63         const struct dom_sid *dom_sid;
64         bool is_enterprise_dc = false;
65
66         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
67         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
68
69         if (!auth_context->sam_ctx) {
70                 DEBUG(0, ("No SAM available, cannot determine local groups\n"));
71                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
72         }
73
74         /* For now, we don't have trusted domains, so we do a very
75          * simple check to see that the user's SID is in *this*
76          * domain, and then trust the user account control.  When we
77          * get trusted domains, we should check it's a trusted domain
78          * in this forest.  This elaborate check is to try and avoid a
79          * nasty security bug if we forget about this later... */
80
81         if (server_info->acct_flags & ACB_SVRTRUST) {
82                 dom_sid = samdb_domain_sid(auth_context->sam_ctx);
83                 if (dom_sid) {
84                         if (dom_sid_in_domain(dom_sid, server_info->account_sid)) {
85                                 is_enterprise_dc = true;
86                         } else {
87                                 DEBUG(2, ("DC %s is not in our domain.  "
88                                           "It will not have Enterprise Domain Controllers membership on this server",
89                                           server_info->account_name));
90                         }
91                 } else {
92                         DEBUG(2, ("Could not obtain local domain SID, "
93                                   "so can not determine if DC %s is a DC of this domain.  "
94                                   "It will not have Enterprise Domain Controllers membership",
95                                   server_info->account_name));
96                 }
97         }
98
99         groupSIDs = talloc_array(tmp_ctx, struct dom_sid *, server_info->n_domain_groups);
100         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(groupSIDs, tmp_ctx);
101         if (!groupSIDs) {
102                 talloc_free(tmp_ctx);
103                 return NT_STATUS_NO_MEMORY;
104         }
105
106         num_groupSIDs = server_info->n_domain_groups;
107
108         for (i=0; i < server_info->n_domain_groups; i++) {
109                 groupSIDs[i] = server_info->domain_groups[i];
110         }
111
112         filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))",
113                                  GROUP_TYPE_BUILTIN_LOCAL_GROUP);
114
115         session_info = talloc(tmp_ctx, struct auth_session_info);
116         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(session_info, tmp_ctx);
117
118         session_info->server_info = talloc_reference(session_info, server_info);
119
120         /* unless set otherwise, the session key is the user session
121          * key from the auth subsystem */ 
122         session_info->session_key = server_info->user_session_key;
123
124         /* Search for each group in the token */
125
126         /* Expands the account SID - this function takes in
127          * memberOf-like values, so we fake one up with the
128          * <SID=S-...> format of DN and then let it expand
129          * them, as long as they meet the filter - so only
130          * builtin groups
131          *
132          * We already have the primary group in the token, so set
133          * 'only childs' flag to true
134          */
135         account_sid_string = dom_sid_string(tmp_ctx, server_info->account_sid);
136         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(account_sid_string, server_info);
137
138         account_sid_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", account_sid_string);
139         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(account_sid_dn, server_info);
140
141         account_sid_blob = data_blob_string_const(account_sid_dn);
142
143         nt_status = authsam_expand_nested_groups(auth_context->sam_ctx, &account_sid_blob, true, filter,
144                                               tmp_ctx, &groupSIDs, &num_groupSIDs);
145         if (!NT_STATUS_IS_OK(nt_status)) {
146                 talloc_free(tmp_ctx);
147                 return nt_status;
148         }
149
150         /* Expands the primary group - this function takes in
151          * memberOf-like values, so we fake one up with the
152          * <SID=S-...> format of DN and then let it expand
153          * them, as long as they meet the filter - so only
154          * builtin groups
155          *
156          * We already have the primary group in the token, so set
157          * 'only childs' flag to true
158          */
159         primary_group_string = dom_sid_string(tmp_ctx, server_info->primary_group_sid);
160         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(primary_group_string, server_info);
161
162         primary_group_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", primary_group_string);
163         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(primary_group_dn, server_info);
164
165         primary_group_blob = data_blob_string_const(primary_group_dn);
166
167         nt_status = authsam_expand_nested_groups(auth_context->sam_ctx, &primary_group_blob, true, filter,
168                                               tmp_ctx, &groupSIDs, &num_groupSIDs);
169         if (!NT_STATUS_IS_OK(nt_status)) {
170                 talloc_free(tmp_ctx);
171                 return nt_status;
172         }
173
174         for (i = 0; i < server_info->n_domain_groups; i++) {
175                 const char *group_string;
176                 const char *group_dn;
177                 DATA_BLOB group_blob;
178                 group_string = dom_sid_string(tmp_ctx, server_info->domain_groups[i]);
179                 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(group_string, server_info);
180
181                 group_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", group_string);
182                 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(group_dn, server_info);
183
184                 group_blob = data_blob_string_const(group_dn);
185
186                 /* This function takes in memberOf values and expands
187                  * them, as long as they meet the filter - so only
188                  * builtin groups */
189                 nt_status = authsam_expand_nested_groups(auth_context->sam_ctx, &group_blob, true, filter,
190                                                       tmp_ctx, &groupSIDs, &num_groupSIDs);
191                 if (!NT_STATUS_IS_OK(nt_status)) {
192                         talloc_free(tmp_ctx);
193                         return nt_status;
194                 }
195         }
196
197         nt_status = security_token_create(session_info,
198                                           auth_context->event_ctx,
199                                           auth_context->lp_ctx,
200                                           server_info->account_sid,
201                                           server_info->primary_group_sid,
202                                           num_groupSIDs,
203                                           groupSIDs,
204                                           server_info->authenticated,
205                                           is_enterprise_dc,
206                                           &session_info->security_token);
207         NT_STATUS_NOT_OK_RETURN_AND_FREE(nt_status, tmp_ctx);
208
209         session_info->credentials = NULL;
210
211         talloc_steal(mem_ctx, session_info);
212         *_session_info = session_info;
213         return NT_STATUS_OK;
214 }
215
216 /**
217  * prints a struct auth_session_info security token to debug output.
218  */
219 void auth_session_info_debug(int dbg_lev, 
220                              const struct auth_session_info *session_info)
221 {
222         if (!session_info) {
223                 DEBUG(dbg_lev, ("Session Info: (NULL)\n"));
224                 return; 
225         }
226
227         security_token_debug(dbg_lev, session_info->security_token);
228 }
229