r6740: make gensec_gssapi.c compile again
[samba.git] / source / auth / gensec / gensec_gssapi.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Kerberos backend for GENSEC
5    
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
7    Copyright (C) Stefan Metzmacher <metze@samba.org> 2005
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/ndr_krb5pac.h"
29 #include "auth/auth.h"
30
31 #undef DBGC_CLASS
32 #define DBGC_CLASS DBGC_AUTH
33
34 static const gss_OID_desc gensec_gss_krb5_mechanism_oid_desc =
35         {9, (void *)discard_const_p(char, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02")};
36
37 static const gss_OID_desc gensec_gss_spnego_mechanism_oid_desc =
38         {6, (void *)discard_const_p(char, "\x2b\x06\x01\x05\x05\x02")};
39
40 struct gensec_gssapi_state {
41         gss_ctx_id_t gssapi_context;
42         struct gss_channel_bindings_struct *input_chan_bindings;
43         gss_name_t server_name;
44         gss_name_t client_name;
45         OM_uint32 want_flags, got_flags;
46         const gss_OID_desc *gss_oid;
47
48         DATA_BLOB session_key;
49         DATA_BLOB pac;
50 };
51 static int gensec_gssapi_destory(void *ptr) 
52 {
53         struct gensec_gssapi_state *gensec_gssapi_state = ptr;
54         OM_uint32 maj_stat, min_stat;
55
56         if (gensec_gssapi_state->gssapi_context != GSS_C_NO_CONTEXT) {
57                 maj_stat = gss_delete_sec_context (&min_stat,
58                                                    &gensec_gssapi_state->gssapi_context,
59                                                    GSS_C_NO_BUFFER);
60         }
61
62         if (gensec_gssapi_state->server_name != GSS_C_NO_NAME) {
63                 maj_stat = gss_release_name(&min_stat, &gensec_gssapi_state->server_name);
64         }
65         if (gensec_gssapi_state->client_name != GSS_C_NO_NAME) {
66                 maj_stat = gss_release_name(&min_stat, &gensec_gssapi_state->client_name);
67         }
68         return 0;
69 }
70
71 static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security)
72 {
73         struct gensec_gssapi_state *gensec_gssapi_state;
74
75         gensec_gssapi_state = talloc(gensec_security, struct gensec_gssapi_state);
76         if (!gensec_gssapi_state) {
77                 return NT_STATUS_NO_MEMORY;
78         }
79
80         gensec_security->private_data = gensec_gssapi_state;
81
82         gensec_gssapi_state->gssapi_context = GSS_C_NO_CONTEXT;
83         gensec_gssapi_state->server_name = GSS_C_NO_NAME;
84         gensec_gssapi_state->client_name = GSS_C_NO_NAME;
85
86         talloc_set_destructor(gensec_gssapi_state, gensec_gssapi_destory); 
87
88         /* TODO: Fill in channel bindings */
89         gensec_gssapi_state->input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS;
90         
91         gensec_gssapi_state->want_flags = 0;
92         gensec_gssapi_state->got_flags = 0;
93
94         gensec_gssapi_state->session_key = data_blob(NULL, 0);
95         gensec_gssapi_state->pac = data_blob(NULL, 0);
96
97         if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
98 #ifndef HAVE_GSSKRB5_GET_INITIATOR_SUBKEY
99                 /* GSSAPI won't give us the session keys, without the
100                  * right hooks.  This is critical when requested, so
101                  * fail outright. */
102                 return NT_STATUS_INVALID_PARAMETER;
103 #endif
104         }
105         if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
106                 gensec_gssapi_state->want_flags |= GSS_C_INTEG_FLAG;
107         }
108         if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
109                 gensec_gssapi_state->want_flags |= GSS_C_CONF_FLAG;
110         }
111         if (gensec_security->want_features & GENSEC_FEATURE_DCE_STYLE) {
112 #ifndef GSS_C_DCE_STYLE
113                 /* GSSAPI DCE_STYLE is critical when requested, so
114                  * fail outright */
115                 return NT_STATUS_INVALID_PARAMETER;
116 #else
117                 gensec_gssapi_state->want_flags |= GSS_C_DCE_STYLE;
118 #endif
119         }
120
121         if ((strcmp(gensec_security->ops->oid, GENSEC_OID_KERBEROS5) == 0)
122                 || (strcmp(gensec_security->ops->oid, GENSEC_OID_KERBEROS5_OLD) == 0)) {
123                 gensec_gssapi_state->gss_oid = &gensec_gss_krb5_mechanism_oid_desc;
124         } else if (strcmp(gensec_security->ops->oid, GENSEC_OID_SPNEGO) == 0) {
125                 gensec_gssapi_state->gss_oid = &gensec_gss_spnego_mechanism_oid_desc;
126         } else {
127                 DEBUG(1, ("gensec_gssapi incorrectly configured - cannot determine gss OID from %s\n", 
128                           gensec_security->ops->oid));
129                 return NT_STATUS_INVALID_PARAMETER;
130         }
131
132         return NT_STATUS_OK;
133 }
134
135 static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_security)
136 {
137         NTSTATUS nt_status;
138         struct gensec_gssapi_state *gensec_gssapi_state;
139
140         nt_status = gensec_gssapi_start(gensec_security);
141         if (!NT_STATUS_IS_OK(nt_status)) {
142                 return nt_status;
143         }
144
145         gensec_gssapi_state = gensec_security->private_data;
146
147         return NT_STATUS_OK;
148 }
149
150 static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_security)
151 {
152         struct gensec_gssapi_state *gensec_gssapi_state;
153         NTSTATUS nt_status;
154         gss_buffer_desc name_token;
155         OM_uint32 maj_stat, min_stat;
156
157         gss_OID_desc hostbased = {10, 
158                                   (void *)discard_const_p(char, "\x2a\x86\x48\x86\xf7\x12"
159                                                           "\x01\x02\x01\x04")};
160
161         nt_status = gensec_gssapi_start(gensec_security);
162         if (!NT_STATUS_IS_OK(nt_status)) {
163                 return nt_status;
164         }
165
166         gensec_gssapi_state = gensec_security->private_data;
167
168         name_token.value = talloc_asprintf(gensec_gssapi_state, "%s@%s", gensec_get_target_service(gensec_security), 
169                                            gensec_get_target_hostname(gensec_security));
170         DEBUG(0, ("name: %s\n", (char *)name_token.value));
171         name_token.length = strlen(name_token.value);
172
173         maj_stat = gss_import_name (&min_stat,
174                                     &name_token,
175                                     &hostbased,
176                                     &gensec_gssapi_state->server_name);
177
178
179         if (maj_stat) {
180                 return NT_STATUS_UNSUCCESSFUL;
181         }
182         return NT_STATUS_OK;
183 }
184
185
186
187 /**
188  * Next state function for the GSSAPI GENSEC mechanism
189  * 
190  * @param gensec_gssapi_state GSSAPI State
191  * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
192  * @param in The request, as a DATA_BLOB
193  * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
194  * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent, 
195  *                or NT_STATUS_OK if the user is authenticated. 
196  */
197
198 static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, 
199                                    TALLOC_CTX *out_mem_ctx, 
200                                    const DATA_BLOB in, DATA_BLOB *out) 
201 {
202         struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
203         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
204         OM_uint32 maj_stat, min_stat;
205         OM_uint32 min_stat2;
206         gss_buffer_desc input_token, output_token;
207         gss_OID gss_oid_p;
208         input_token.length = in.length;
209         input_token.value = in.data;
210
211         switch (gensec_security->gensec_role) {
212         case GENSEC_CLIENT:
213         {
214                 maj_stat = gss_init_sec_context(&min_stat, 
215                                                 GSS_C_NO_CREDENTIAL, 
216                                                 &gensec_gssapi_state->gssapi_context, 
217                                                 gensec_gssapi_state->server_name, 
218                                                 discard_const_p(gss_OID_desc, gensec_gssapi_state->gss_oid),
219                                                 gensec_gssapi_state->want_flags, 
220                                                 0, 
221                                                 gensec_gssapi_state->input_chan_bindings,
222                                                 &input_token, 
223                                                 NULL, 
224                                                 &output_token, 
225                                                 &gensec_gssapi_state->got_flags, /* ret flags */
226                                                 NULL);
227                 break;
228         }
229         case GENSEC_SERVER:
230         {
231                 maj_stat = gss_accept_sec_context(&min_stat, 
232                                                   &gensec_gssapi_state->gssapi_context, 
233                                                   GSS_C_NO_CREDENTIAL, 
234                                                   &input_token, 
235                                                   gensec_gssapi_state->input_chan_bindings,
236                                                   &gensec_gssapi_state->client_name, 
237                                                   &gss_oid_p,
238                                                   &output_token, 
239                                                   &gensec_gssapi_state->got_flags, 
240                                                   NULL, 
241                                                   NULL);
242                 gensec_gssapi_state->gss_oid = gss_oid_p;
243                 break;
244         }
245         default:
246                 return NT_STATUS_INVALID_PARAMETER;
247                 
248         }
249
250         *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
251         gss_release_buffer(&min_stat2, &output_token);
252
253         if (maj_stat == GSS_S_COMPLETE) {
254                 return NT_STATUS_OK;
255         } else if (maj_stat == GSS_S_CONTINUE_NEEDED) {
256                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
257         } else {
258                 gss_buffer_desc msg1, msg2;
259                 OM_uint32 msg_ctx = 0;
260                 
261                 msg1.value = NULL;
262                 msg2.value = NULL;
263                 gss_display_status(&min_stat2, maj_stat, GSS_C_GSS_CODE,
264                                    GSS_C_NULL_OID, &msg_ctx, &msg1);
265                 gss_display_status(&min_stat2, min_stat, GSS_C_MECH_CODE,
266                                    GSS_C_NULL_OID, &msg_ctx, &msg2);
267                 DEBUG(1, ("gensec_gssapi_update: %s : %s\n", (char *)msg1.value, (char *)msg2.value));
268                 gss_release_buffer(&min_stat2, &msg1);
269                 gss_release_buffer(&min_stat2, &msg2);
270
271                 return nt_status;
272         }
273         
274 }
275
276 static NTSTATUS gensec_gssapi_wrap(struct gensec_security *gensec_security, 
277                                    TALLOC_CTX *mem_ctx, 
278                                    const DATA_BLOB *in, 
279                                    DATA_BLOB *out)
280 {
281         struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
282         OM_uint32 maj_stat, min_stat;
283         gss_buffer_desc input_token, output_token;
284         int conf_state;
285         input_token.length = in->length;
286         input_token.value = in->data;
287         
288         maj_stat = gss_wrap(&min_stat, 
289                             gensec_gssapi_state->gssapi_context, 
290                             gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
291                             GSS_C_QOP_DEFAULT,
292                             &input_token,
293                             &conf_state,
294                             &output_token);
295         if (GSS_ERROR(maj_stat)) {
296                 return NT_STATUS_ACCESS_DENIED;
297         }
298         *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
299
300         gss_release_buffer(&min_stat, &output_token);
301
302         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
303             && !conf_state) {
304                 return NT_STATUS_ACCESS_DENIED;
305         }
306         return NT_STATUS_OK;
307 }
308
309 static NTSTATUS gensec_gssapi_unwrap(struct gensec_security *gensec_security, 
310                                      TALLOC_CTX *mem_ctx, 
311                                      const DATA_BLOB *in, 
312                                      DATA_BLOB *out)
313 {
314         struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
315         OM_uint32 maj_stat, min_stat;
316         gss_buffer_desc input_token, output_token;
317         int conf_state;
318         gss_qop_t qop_state;
319         input_token.length = in->length;
320         input_token.value = in->data;
321         
322         maj_stat = gss_unwrap(&min_stat, 
323                               gensec_gssapi_state->gssapi_context, 
324                               &input_token,
325                               &output_token, 
326                               &conf_state,
327                               &qop_state);
328         if (GSS_ERROR(maj_stat)) {
329                 return NT_STATUS_ACCESS_DENIED;
330         }
331         *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
332
333         gss_release_buffer(&min_stat, &output_token);
334         
335         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
336             && !conf_state) {
337                 return NT_STATUS_ACCESS_DENIED;
338         }
339         return NT_STATUS_OK;
340 }
341
342 static size_t gensec_gssapi_sig_size(struct gensec_security *gensec_security) 
343 {
344         /* not const but work for DCERPC packets and arcfour */
345         return 45;
346 }
347
348 static NTSTATUS gensec_gssapi_seal_packet(struct gensec_security *gensec_security, 
349                                           TALLOC_CTX *mem_ctx, 
350                                           uint8_t *data, size_t length, 
351                                           const uint8_t *whole_pdu, size_t pdu_length, 
352                                           DATA_BLOB *sig)
353 {
354         struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
355         OM_uint32 maj_stat, min_stat;
356         gss_buffer_desc input_token, output_token;
357         int conf_state;
358         ssize_t sig_length = 0;
359
360         input_token.length = length;
361         input_token.value = data;
362         
363         maj_stat = gss_wrap(&min_stat, 
364                             gensec_gssapi_state->gssapi_context,
365                             gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
366                             GSS_C_QOP_DEFAULT,
367                             &input_token,
368                             &conf_state,
369                             &output_token);
370         if (GSS_ERROR(maj_stat)) {
371                 return NT_STATUS_ACCESS_DENIED;
372         }
373
374         if (output_token.length < length) {
375                 return NT_STATUS_INTERNAL_ERROR;
376         }
377
378         sig_length = 45;
379
380         memcpy(data, ((uint8_t *)output_token.value) + sig_length, length);
381         *sig = data_blob_talloc(mem_ctx, (uint8_t *)output_token.value, sig_length);
382
383 DEBUG(0,("gensec_gssapi_seal_packet: siglen: %d inlen: %d, wrap_len: %d\n", sig->length, length, output_token.length - sig_length));
384 dump_data(0,sig->data, sig->length);
385 dump_data(0,data, length);
386 dump_data(0,((uint8_t *)output_token.value) + sig_length, output_token.length - sig_length);
387
388         gss_release_buffer(&min_stat, &output_token);
389
390         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
391             && !conf_state) {
392                 return NT_STATUS_ACCESS_DENIED;
393         }
394         return NT_STATUS_OK;
395 }
396
397 static NTSTATUS gensec_gssapi_unseal_packet(struct gensec_security *gensec_security, 
398                                             TALLOC_CTX *mem_ctx, 
399                                             uint8_t *data, size_t length, 
400                                             const uint8_t *whole_pdu, size_t pdu_length,
401                                             const DATA_BLOB *sig)
402 {
403         struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
404         OM_uint32 maj_stat, min_stat;
405         gss_buffer_desc input_token, output_token;
406         int conf_state;
407         gss_qop_t qop_state;
408         DATA_BLOB in;
409
410 DEBUG(0,("gensec_gssapi_unseal_packet: siglen: %d\n", sig->length));
411 dump_data(0,sig->data, sig->length);
412
413         in = data_blob_talloc(mem_ctx, NULL, sig->length + length);
414
415         memcpy(in.data, sig->data, sig->length);
416         memcpy(in.data + sig->length, data, length);
417
418         input_token.length = in.length;
419         input_token.value = in.data;
420         
421         maj_stat = gss_unwrap(&min_stat, 
422                               gensec_gssapi_state->gssapi_context, 
423                               &input_token,
424                               &output_token, 
425                               &conf_state,
426                               &qop_state);
427         if (GSS_ERROR(maj_stat)) {
428                 return NT_STATUS_ACCESS_DENIED;
429         }
430
431         if (output_token.length != length) {
432                 return NT_STATUS_INTERNAL_ERROR;
433         }
434
435         memcpy(data, output_token.value, length);
436
437         gss_release_buffer(&min_stat, &output_token);
438         
439         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
440             && !conf_state) {
441                 return NT_STATUS_ACCESS_DENIED;
442         }
443         return NT_STATUS_OK;
444 }
445
446 static NTSTATUS gensec_gssapi_sign_packet(struct gensec_security *gensec_security, 
447                                           TALLOC_CTX *mem_ctx, 
448                                           const uint8_t *data, size_t length, 
449                                           const uint8_t *whole_pdu, size_t pdu_length, 
450                                           DATA_BLOB *sig)
451 {
452         struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
453         OM_uint32 maj_stat, min_stat;
454         gss_buffer_desc input_token, output_token;
455         int conf_state;
456         ssize_t sig_length = 0;
457
458         input_token.length = length;
459         input_token.value = discard_const_p(uint8_t *, data);
460
461         maj_stat = gss_wrap(&min_stat, 
462                             gensec_gssapi_state->gssapi_context,
463                             0,
464                             GSS_C_QOP_DEFAULT,
465                             &input_token,
466                             &conf_state,
467                             &output_token);
468         if (GSS_ERROR(maj_stat)) {
469                 return NT_STATUS_ACCESS_DENIED;
470         }
471
472         if (output_token.length < length) {
473                 return NT_STATUS_INTERNAL_ERROR;
474         }
475
476         sig_length = 45;
477
478         /*memcpy(data, ((uint8_t *)output_token.value) + sig_length, length);*/
479         *sig = data_blob_talloc(mem_ctx, (uint8_t *)output_token.value, sig_length);
480
481 DEBUG(0,("gensec_gssapi_sign_packet: siglen: %d\n", sig->length));
482 dump_data(0,sig->data, sig->length);
483
484         gss_release_buffer(&min_stat, &output_token);
485
486         return NT_STATUS_OK;
487 }
488
489 static NTSTATUS gensec_gssapi_check_packet(struct gensec_security *gensec_security, 
490                                            TALLOC_CTX *mem_ctx, 
491                                            const uint8_t *data, size_t length, 
492                                            const uint8_t *whole_pdu, size_t pdu_length, 
493                                            const DATA_BLOB *sig)
494 {
495         struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
496         OM_uint32 maj_stat, min_stat;
497         gss_buffer_desc input_token, output_token;
498         int conf_state;
499         gss_qop_t qop_state;
500         DATA_BLOB in;
501
502 DEBUG(0,("gensec_gssapi_check_packet: siglen: %d\n", sig->length));
503 dump_data(0,sig->data, sig->length);
504
505         in = data_blob_talloc(mem_ctx, NULL, sig->length + length);
506
507         memcpy(in.data, sig->data, sig->length);
508         memcpy(in.data + sig->length, data, length);
509
510         input_token.length = in.length;
511         input_token.value = in.data;
512         
513         maj_stat = gss_unwrap(&min_stat, 
514                               gensec_gssapi_state->gssapi_context, 
515                               &input_token,
516                               &output_token, 
517                               &conf_state,
518                               &qop_state);
519         if (GSS_ERROR(maj_stat)) {
520                 return NT_STATUS_ACCESS_DENIED;
521         }
522
523         if (output_token.length != length) {
524                 return NT_STATUS_INTERNAL_ERROR;
525         }
526
527         /*memcpy(data, output_token.value, length);*/
528
529         gss_release_buffer(&min_stat, &output_token);
530
531         return NT_STATUS_OK;
532 }
533
534 static BOOL gensec_gssapi_have_feature(struct gensec_security *gensec_security, 
535                                        uint32_t feature) 
536 {
537         struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
538         if (feature & GENSEC_FEATURE_SIGN) {
539                 return gensec_gssapi_state->got_flags & GSS_C_INTEG_FLAG;
540         }
541         if (feature & GENSEC_FEATURE_SEAL) {
542                 return gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG;
543         }
544         if (feature & GENSEC_FEATURE_SESSION_KEY) {
545 #ifdef HAVE_GSSKRB5_GET_INITIATOR_SUBKEY
546                 if ((gensec_gssapi_state->gss_oid->length == gensec_gss_krb5_mechanism_oid_desc.length)
547                     && (memcmp(gensec_gssapi_state->gss_oid->elements, gensec_gss_krb5_mechanism_oid_desc.elements, gensec_gssapi_state->gss_oid->length) == 0)) {
548                         return True;
549                 }
550 #endif 
551         }
552         return False;
553 }
554
555 static NTSTATUS gensec_gssapi_session_key(struct gensec_security *gensec_security, 
556                                           DATA_BLOB *session_key) 
557 {
558         struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
559         
560         if (gensec_gssapi_state->session_key.data) {
561                 *session_key = gensec_gssapi_state->session_key;
562                 return NT_STATUS_OK;
563         }
564
565 #ifdef HAVE_GSSKRB5_GET_INITIATOR_SUBKEY
566         if ((gensec_gssapi_state->gss_oid->length == gensec_gss_krb5_mechanism_oid_desc.length)
567             && (memcmp(gensec_gssapi_state->gss_oid->elements, gensec_gss_krb5_mechanism_oid_desc.elements, gensec_gssapi_state->gss_oid->length) == 0)) {
568                 OM_uint32 maj_stat, min_stat;
569                 gss_buffer_desc skey;
570                 
571                 maj_stat = gsskrb5_get_initiator_subkey(&min_stat, 
572                                                         gensec_gssapi_state->gssapi_context, 
573                                                         &skey);
574                 
575                 if (maj_stat == 0) {
576                         DEBUG(10, ("Got KRB5 session key of length %d\n",  skey.length));
577                         gensec_gssapi_state->session_key = data_blob_talloc(gensec_gssapi_state, 
578                                                                             skey.value, skey.length);
579                         *session_key = gensec_gssapi_state->session_key;
580                         dump_data_pw("KRB5 Session Key:\n", session_key->data, session_key->length);
581                         
582                         gss_release_buffer(&min_stat, &skey);
583                         return NT_STATUS_OK;
584                 }
585                 return NT_STATUS_NO_USER_SESSION_KEY;
586         }
587 #endif
588         
589         DEBUG(1, ("NO session key for this mech\n"));
590         return NT_STATUS_NO_USER_SESSION_KEY;
591 }
592
593 static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_security,
594                                          struct auth_session_info **_session_info) 
595 {
596         NTSTATUS nt_status;
597         struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
598         struct auth_serversupplied_info *server_info = NULL;
599         struct auth_session_info *session_info = NULL;
600         char *p;
601         char *principal;
602         const char *account_name;
603         const char *realm;
604         OM_uint32 maj_stat, min_stat;
605         gss_buffer_desc name_token;
606         
607         maj_stat = gss_display_name (&min_stat,
608                                      gensec_gssapi_state->client_name,
609                                      &name_token,
610                                      NULL);
611         if (maj_stat) {
612                 return NT_STATUS_FOOBAR;
613         }
614
615         principal = talloc_strndup(gensec_gssapi_state, name_token.value, name_token.length);
616
617         gss_release_buffer(&min_stat, &name_token);
618
619         NT_STATUS_HAVE_NO_MEMORY(principal);
620
621         p = strchr(principal, '@');
622         if (p) {
623                 *p = '\0';
624                 p++;
625                 realm = p;
626         } else {
627                 realm = lp_realm();
628         }
629         account_name = principal;
630
631         /* IF we have the PAC - otherwise we need to get this
632          * data from elsewere - local ldb, or (TODO) lookup of some
633          * kind... 
634          *
635          * when heimdal can generate the PAC, we should fail if there's
636          * no PAC present
637          */
638
639         {
640                 DATA_BLOB user_sess_key = data_blob(NULL, 0);
641                 DATA_BLOB lm_sess_key = data_blob(NULL, 0);
642                 /* TODO: should we pass the krb5 session key in here? */
643                 nt_status = sam_get_server_info(gensec_gssapi_state, account_name, realm,
644                                                 user_sess_key, lm_sess_key,
645                                                 &server_info);
646                 talloc_free(principal);
647                 NT_STATUS_NOT_OK_RETURN(nt_status);
648         }
649
650         /* references the server_info into the session_info */
651         nt_status = auth_generate_session_info(gensec_gssapi_state, server_info, &session_info);
652         talloc_free(server_info);
653         NT_STATUS_NOT_OK_RETURN(nt_status);
654
655         nt_status = gensec_gssapi_session_key(gensec_security, &session_info->session_key);
656         NT_STATUS_NOT_OK_RETURN(nt_status);
657
658         *_session_info = session_info;
659
660         return NT_STATUS_OK;
661 }
662
663 /* As a server, this could in theory accept any GSSAPI mech */
664 static const struct gensec_security_ops gensec_gssapi_krb5_security_ops = {
665         .name           = "gssapi_krb5",
666         .sasl_name      = "GSSAPI",
667         .auth_type      = DCERPC_AUTH_TYPE_KRB5,
668         .oid            = GENSEC_OID_KERBEROS5,
669         .client_start   = gensec_gssapi_client_start,
670         .server_start   = gensec_gssapi_server_start,
671         .update         = gensec_gssapi_update,
672         .session_key    = gensec_gssapi_session_key,
673         .session_info   = gensec_gssapi_session_info,
674         .sig_size       = gensec_gssapi_sig_size,
675         .sign_packet    = gensec_gssapi_sign_packet,
676         .check_packet   = gensec_gssapi_check_packet,
677         .seal_packet    = gensec_gssapi_seal_packet,
678         .unseal_packet  = gensec_gssapi_unseal_packet,
679         .wrap           = gensec_gssapi_wrap,
680         .unwrap         = gensec_gssapi_unwrap,
681         .have_feature   = gensec_gssapi_have_feature,
682         .enabled        = False
683
684 };
685
686 /* As a server, this could in theory accept any GSSAPI mech */
687 static const struct gensec_security_ops gensec_gssapi_ms_krb5_security_ops = {
688         .name           = "gssapi_ms_krb5",
689         .oid            = GENSEC_OID_KERBEROS5_OLD,
690         .client_start   = gensec_gssapi_client_start,
691         .server_start   = gensec_gssapi_server_start,
692         .update         = gensec_gssapi_update,
693         .session_key    = gensec_gssapi_session_key,
694         .session_info   = gensec_gssapi_session_info,
695         .sig_size       = gensec_gssapi_sig_size,
696         .sign_packet    = gensec_gssapi_sign_packet,
697         .check_packet   = gensec_gssapi_check_packet,
698         .seal_packet    = gensec_gssapi_seal_packet,
699         .unseal_packet  = gensec_gssapi_unseal_packet,
700         .wrap           = gensec_gssapi_wrap,
701         .unwrap         = gensec_gssapi_unwrap,
702         .have_feature   = gensec_gssapi_have_feature,
703         .enabled        = False
704
705 };
706
707 static const struct gensec_security_ops gensec_gssapi_spnego_security_ops = {
708         .name           = "gssapi_spnego",
709         .sasl_name      = "GSS-SPNEGO",
710         .oid            = GENSEC_OID_SPNEGO,
711         .client_start   = gensec_gssapi_client_start,
712         .server_start   = gensec_gssapi_server_start,
713         .update         = gensec_gssapi_update,
714         .session_key    = gensec_gssapi_session_key,
715         .sig_size       = gensec_gssapi_sig_size,
716         .sign_packet    = gensec_gssapi_sign_packet,
717         .check_packet   = gensec_gssapi_check_packet,
718         .seal_packet    = gensec_gssapi_seal_packet,
719         .unseal_packet  = gensec_gssapi_unseal_packet,
720         .wrap           = gensec_gssapi_wrap,
721         .unwrap         = gensec_gssapi_unwrap,
722         .have_feature   = gensec_gssapi_have_feature,
723         .enabled        = False
724 };
725
726 NTSTATUS gensec_gssapi_init(void)
727 {
728         NTSTATUS ret;
729
730         ret = gensec_register(&gensec_gssapi_krb5_security_ops);
731         if (!NT_STATUS_IS_OK(ret)) {
732                 DEBUG(0,("Failed to register '%s' gensec backend!\n",
733                         gensec_gssapi_krb5_security_ops.name));
734                 return ret;
735         }
736
737
738         ret = gensec_register(&gensec_gssapi_ms_krb5_security_ops);
739         if (!NT_STATUS_IS_OK(ret)) {
740                 DEBUG(0,("Failed to register '%s' gensec backend!\n",
741                         gensec_gssapi_ms_krb5_security_ops.name));
742                 return ret;
743         }
744
745         ret = gensec_register(&gensec_gssapi_spnego_security_ops);
746         if (!NT_STATUS_IS_OK(ret)) {
747                 DEBUG(0,("Failed to register '%s' gensec backend!\n",
748                         gensec_gssapi_spnego_security_ops.name));
749                 return ret;
750         }
751
752         return ret;
753 }