TODO: save PAC data in netsamlogon cache ? s3-auth Add auth hook for PAC parsing
[metze/samba/wip.git] / source3 / auth / auth_generic.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    handle GENSEC authentication, server side
5
6    Copyright (C) Andrew Tridgell      2001
7    Copyright (C) Andrew Bartlett 2001-2003,2011
8    Copyright (C) Simo Sorce 2010.
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.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "auth/gensec/gensec.h"
28 #include "lib/param/param.h"
29 #ifdef HAVE_KRB5
30 #include "libcli/auth/krb5_wrap.h"
31 #endif
32
33 static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx,
34                                                 TALLOC_CTX *mem_ctx,
35                                                 struct smb_krb5_context *smb_krb5_context,
36                                                 DATA_BLOB *pac_blob,
37                                                 const char *princ_name,
38                                                 const struct tsocket_address *remote_address,
39                                                 uint32_t session_info_flags,
40                                                 struct auth_session_info **session_info)
41 {
42         TALLOC_CTX *tmp_ctx;
43         struct PAC_DATA *pac_data = NULL;
44         struct PAC_LOGON_INFO *logon_info = NULL;
45         unsigned int i;
46         bool is_mapped;
47         bool is_guest;
48         char *ntuser;
49         char *ntdomain;
50         char *username;
51         char *rhost;
52         struct passwd *pw;
53         NTSTATUS status;
54         int rc;
55
56         tmp_ctx = talloc_new(mem_ctx);
57         if (!tmp_ctx) {
58                 return NT_STATUS_NO_MEMORY;
59         }
60
61         if (pac_blob) {
62 #ifdef HAVE_KRB5
63                 status = kerberos_decode_pac(tmp_ctx,
64                                      *pac_blob,
65                                      NULL, NULL, NULL, NULL, 0, &pac_data);
66 #else
67                 status = NT_STATUS_ACCESS_DENIED;
68 #endif
69                 if (!NT_STATUS_IS_OK(status)) {
70                         goto done;
71                 }
72
73                 /* get logon name and logon info */
74                 for (i = 0; i < pac_data->num_buffers; i++) {
75                         struct PAC_BUFFER *data_buf = &pac_data->buffers[i];
76
77                         switch (data_buf->type) {
78                         case PAC_TYPE_LOGON_INFO:
79                                 if (!data_buf->info) {
80                                         break;
81                                 }
82                                 logon_info = data_buf->info->logon_info.info;
83                                 break;
84                         default:
85                                 break;
86                         }
87                 }
88                 if (!logon_info) {
89                         DEBUG(1, ("Invalid PAC data, missing logon info!\n"));
90                         status = NT_STATUS_NOT_FOUND;
91                         goto done;
92                 }
93         }
94
95         rc = get_remote_hostname(remote_address,
96                                  &rhost,
97                                  tmp_ctx);
98         if (rc < 0) {
99                 status = NT_STATUS_NO_MEMORY;
100                 goto done;
101         }
102         if (strequal(rhost, "UNKNOWN")) {
103                 rhost = tsocket_address_inet_addr_string(remote_address,
104                                                          tmp_ctx);
105                 if (rhost == NULL) {
106                         status = NT_STATUS_NO_MEMORY;
107                         goto done;
108                 }
109         }
110
111         status = get_user_from_kerberos_info(tmp_ctx, rhost,
112                                              princ_name, logon_info,
113                                              &is_mapped, &is_guest,
114                                              &ntuser, &ntdomain,
115                                              &username, &pw);
116         if (!NT_STATUS_IS_OK(status)) {
117                 DEBUG(1, ("Failed to map kerberos principal to system user "
118                           "(%s)\n", nt_errstr(status)));
119                 status = NT_STATUS_ACCESS_DENIED;
120                 goto done;
121         }
122
123         /* TODO: save PAC data in netsamlogon cache ? */
124
125         status = make_session_info_krb5(mem_ctx,
126                                         ntuser, ntdomain, username, pw,
127                                         logon_info, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */,
128                                         session_info);
129         if (!NT_STATUS_IS_OK(status)) {
130                 DEBUG(1, ("Failed to map kerberos pac to server info (%s)\n",
131                           nt_errstr(status)));
132                 status = NT_STATUS_ACCESS_DENIED;
133                 goto done;
134         }
135
136         DEBUG(5, (__location__ "OK: user: %s domain: %s client: %s\n",
137                   ntuser, ntdomain, rhost));
138
139         status = NT_STATUS_OK;
140
141 done:
142         TALLOC_FREE(tmp_ctx);
143         return status;
144 }
145
146 NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx,
147                               const struct tsocket_address *remote_address,
148                               struct gensec_security **gensec_security_out)
149 {
150         struct gensec_security *gensec_security;
151         struct auth_context *auth_context;
152         NTSTATUS nt_status;
153
154         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
155         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
156
157         nt_status = make_auth_context_subsystem(tmp_ctx, &auth_context);
158         if (!NT_STATUS_IS_OK(nt_status)) {
159                 TALLOC_FREE(tmp_ctx);
160                 return nt_status;
161         }
162
163         if (auth_context->prepare_gensec) {
164                 nt_status = auth_context->prepare_gensec(tmp_ctx,
165                                                          &gensec_security);
166                 if (!NT_STATUS_IS_OK(nt_status)) {
167                         TALLOC_FREE(tmp_ctx);
168                         return nt_status;
169                 }
170         } else {
171                 struct gensec_settings *gensec_settings;
172                 struct loadparm_context *lp_ctx;
173
174                 struct auth4_context *auth4_context = talloc_zero(tmp_ctx, struct auth4_context);
175                 if (auth4_context == NULL) {
176                         DEBUG(10, ("failed to allocate auth4_context failed\n"));
177                         TALLOC_FREE(tmp_ctx);
178                         return NT_STATUS_NO_MEMORY;
179                 }
180                 auth4_context->generate_session_info_pac = auth3_generate_session_info_pac;
181
182                 lp_ctx = loadparm_init_s3(tmp_ctx, loadparm_s3_context());
183                 if (lp_ctx == NULL) {
184                         DEBUG(10, ("loadparm_init_s3 failed\n"));
185                         TALLOC_FREE(tmp_ctx);
186                         return NT_STATUS_INVALID_SERVER_STATE;
187                 }
188
189                 gensec_settings = lpcfg_gensec_settings(tmp_ctx, lp_ctx);
190                 if (lp_ctx == NULL) {
191                         DEBUG(10, ("lpcfg_gensec_settings failed\n"));
192                         TALLOC_FREE(tmp_ctx);
193                         return NT_STATUS_NO_MEMORY;
194                 }
195
196                 gensec_settings->backends = talloc_zero_array(gensec_settings, struct gensec_security_ops *, 2);
197                 if (gensec_settings->backends == NULL) {
198                         TALLOC_FREE(tmp_ctx);
199                         return NT_STATUS_NO_MEMORY;
200                 }
201
202                 gensec_settings->backends[0] = &gensec_ntlmssp3_server_ops;
203
204                 nt_status = gensec_server_start(tmp_ctx, gensec_settings,
205                                                 auth4_context, &gensec_security);
206
207                 if (!NT_STATUS_IS_OK(nt_status)) {
208                         TALLOC_FREE(tmp_ctx);
209                         return nt_status;
210                 }
211                 talloc_unlink(tmp_ctx, lp_ctx);
212                 talloc_unlink(tmp_ctx, gensec_settings);
213                 talloc_unlink(tmp_ctx, auth4_context);
214         }
215
216         nt_status = gensec_set_remote_address(gensec_security,
217                                               remote_address);
218         if (!NT_STATUS_IS_OK(nt_status)) {
219                 TALLOC_FREE(tmp_ctx);
220                 return nt_status;
221         }
222
223         *gensec_security_out = talloc_steal(mem_ctx, gensec_security);
224         TALLOC_FREE(tmp_ctx);
225         return NT_STATUS_OK;
226 }