s4-auth Add function to obtain any user's session_info from a given LDB
[ab/samba.git/.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 "auth/auth_sam.h"
27 #include "libcli/security/security.h"
28 #include "libcli/auth/libcli_auth.h"
29 #include "dsdb/samdb/samdb.h"
30 #include "auth/session_proto.h"
31
32 _PUBLIC_ struct auth_session_info *anonymous_session(TALLOC_CTX *mem_ctx, 
33                                             struct loadparm_context *lp_ctx)
34 {
35         NTSTATUS nt_status;
36         struct auth_session_info *session_info = NULL;
37         nt_status = auth_anonymous_session_info(mem_ctx, lp_ctx, &session_info);
38         if (!NT_STATUS_IS_OK(nt_status)) {
39                 return NULL;
40         }
41         return session_info;
42 }
43
44 _PUBLIC_ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx,
45                                              struct loadparm_context *lp_ctx, /* Optional, if you don't want privilages */
46                                              struct ldb_context *sam_ctx, /* Optional, if you don't want local groups */
47                                              struct auth_serversupplied_info *server_info,
48                                              uint32_t session_info_flags,
49                                              struct auth_session_info **_session_info)
50 {
51         struct auth_session_info *session_info;
52         NTSTATUS nt_status;
53         unsigned int i, num_groupSIDs = 0;
54         const char *account_sid_string;
55         const char *account_sid_dn;
56         DATA_BLOB account_sid_blob;
57         const char *primary_group_string;
58         const char *primary_group_dn;
59         DATA_BLOB primary_group_blob;
60
61         const char *filter;
62
63         struct dom_sid **groupSIDs = NULL;
64         const struct dom_sid *anonymous_sid, *system_sid;
65
66         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
67         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
68
69         session_info = talloc(tmp_ctx, struct auth_session_info);
70         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(session_info, tmp_ctx);
71
72         session_info->server_info = talloc_reference(session_info, server_info);
73
74         /* unless set otherwise, the session key is the user session
75          * key from the auth subsystem */ 
76         session_info->session_key = server_info->user_session_key;
77
78         anonymous_sid = dom_sid_parse_talloc(tmp_ctx, SID_NT_ANONYMOUS);
79         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(anonymous_sid, tmp_ctx);
80
81         system_sid = dom_sid_parse_talloc(tmp_ctx, SID_NT_SYSTEM);
82         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(system_sid, tmp_ctx);
83
84         groupSIDs = talloc_array(tmp_ctx, struct dom_sid *, server_info->n_domain_groups);
85         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(groupSIDs, tmp_ctx);
86         if (!groupSIDs) {
87                 talloc_free(tmp_ctx);
88                 return NT_STATUS_NO_MEMORY;
89         }
90
91         num_groupSIDs = server_info->n_domain_groups;
92
93         for (i=0; i < server_info->n_domain_groups; i++) {
94                 groupSIDs[i] = server_info->domain_groups[i];
95         }
96
97         if (dom_sid_equal(anonymous_sid, server_info->account_sid)) {
98                 /* Don't expand nested groups of system, anonymous etc*/
99         } else if (dom_sid_equal(system_sid, server_info->account_sid)) {
100                 /* Don't expand nested groups of system, anonymous etc*/
101         } else if (sam_ctx) {
102                 filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))",
103                                          GROUP_TYPE_BUILTIN_LOCAL_GROUP);
104
105                 /* Search for each group in the token */
106
107                 /* Expands the account SID - this function takes in
108                  * memberOf-like values, so we fake one up with the
109                  * <SID=S-...> format of DN and then let it expand
110                  * them, as long as they meet the filter - so only
111                  * builtin groups
112                  *
113                  * We already have the primary group in the token, so set
114                  * 'only childs' flag to true
115                  */
116                 account_sid_string = dom_sid_string(tmp_ctx, server_info->account_sid);
117                 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(account_sid_string, server_info);
118                 
119                 account_sid_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", account_sid_string);
120                 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(account_sid_dn, server_info);
121                 
122                 account_sid_blob = data_blob_string_const(account_sid_dn);
123                 
124                 nt_status = dsdb_expand_nested_groups(sam_ctx, &account_sid_blob, true, filter,
125                                                       tmp_ctx, &groupSIDs, &num_groupSIDs);
126                 if (!NT_STATUS_IS_OK(nt_status)) {
127                         talloc_free(tmp_ctx);
128                         return nt_status;
129                 }
130
131                 /* Expands the primary group - this function takes in
132                  * memberOf-like values, so we fake one up with the
133                  * <SID=S-...> format of DN and then let it expand
134                  * them, as long as they meet the filter - so only
135                  * builtin groups
136                  *
137                  * We already have the primary group in the token, so set
138                  * 'only childs' flag to true
139                  */
140                 primary_group_string = dom_sid_string(tmp_ctx, server_info->primary_group_sid);
141                 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(primary_group_string, server_info);
142                 
143                 primary_group_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", primary_group_string);
144                 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(primary_group_dn, server_info);
145                 
146                 primary_group_blob = data_blob_string_const(primary_group_dn);
147                 
148                 nt_status = dsdb_expand_nested_groups(sam_ctx, &primary_group_blob, true, filter,
149                                                       tmp_ctx, &groupSIDs, &num_groupSIDs);
150                 if (!NT_STATUS_IS_OK(nt_status)) {
151                         talloc_free(tmp_ctx);
152                         return nt_status;
153                 }
154                 
155                 for (i = 0; i < server_info->n_domain_groups; i++) {
156                         char *group_string;
157                         const char *group_dn;
158                         DATA_BLOB group_blob;
159                         
160                         group_string = dom_sid_string(tmp_ctx,
161                                                       server_info->domain_groups[i]);
162                         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(group_string, server_info);
163                         
164                         group_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", group_string);
165                         talloc_free(group_string);
166                         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(group_dn, server_info);
167                         group_blob = data_blob_string_const(group_dn);
168                         
169                         /* This function takes in memberOf values and expands
170                          * them, as long as they meet the filter - so only
171                          * builtin groups */
172                         nt_status = dsdb_expand_nested_groups(sam_ctx, &group_blob, true, filter,
173                                                               tmp_ctx, &groupSIDs, &num_groupSIDs);
174                         if (!NT_STATUS_IS_OK(nt_status)) {
175                                 talloc_free(tmp_ctx);
176                                 return nt_status;
177                         }
178                 }
179         }
180
181         nt_status = security_token_create(session_info,
182                                           lp_ctx,
183                                           server_info->account_sid,
184                                           server_info->primary_group_sid,
185                                           num_groupSIDs,
186                                           groupSIDs,
187                                           session_info_flags,
188                                           &session_info->security_token);
189         NT_STATUS_NOT_OK_RETURN_AND_FREE(nt_status, tmp_ctx);
190
191         session_info->credentials = NULL;
192
193         talloc_steal(mem_ctx, session_info);
194         *_session_info = session_info;
195         talloc_free(tmp_ctx);
196         return NT_STATUS_OK;
197 }
198
199 /* Produce a session_info for an arbitary DN or principal in the local
200  * DB, assuming the local DB holds all the groups
201  *
202  * Supply either a principal or a DN
203  */
204 NTSTATUS authsam_get_session_info_principal(TALLOC_CTX *mem_ctx,
205                                             struct loadparm_context *lp_ctx,
206                                             struct ldb_context *sam_ctx,
207                                             const char *principal,
208                                             struct ldb_dn *user_dn,
209                                             uint32_t session_info_flags,
210                                             struct auth_session_info **session_info)
211 {
212         NTSTATUS nt_status;
213         struct auth_serversupplied_info *server_info;
214         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
215         if (!tmp_ctx) {
216                 return NT_STATUS_NO_MEMORY;
217         }
218         nt_status = authsam_get_server_info_principal(tmp_ctx, lp_ctx, sam_ctx,
219                                                       principal, user_dn,
220                                                       &server_info);
221         if (!NT_STATUS_IS_OK(nt_status)) {
222                 talloc_free(tmp_ctx);
223                 return nt_status;
224         }
225
226         nt_status = auth_generate_session_info(tmp_ctx, lp_ctx, sam_ctx,
227                                                server_info, session_info_flags,
228                                                session_info);
229
230         if (NT_STATUS_IS_OK(nt_status)) {
231                 talloc_steal(mem_ctx, *session_info);
232         }
233         talloc_free(tmp_ctx);
234         return NT_STATUS_OK;
235 }
236
237 /**
238  * prints a struct auth_session_info security token to debug output.
239  */
240 void auth_session_info_debug(int dbg_lev, 
241                              const struct auth_session_info *session_info)
242 {
243         if (!session_info) {
244                 DEBUG(dbg_lev, ("Session Info: (NULL)\n"));
245                 return; 
246         }
247
248         security_token_debug(0, dbg_lev, session_info->security_token);
249 }
250