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