s3-auth rename auth_ntlmssp_prepare() -> auth_generic_prepare()
[mat/samba.git] / source3 / smbd / seal.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB Transport encryption (sealing) code - server code.
4    Copyright (C) Jeremy Allison 2007.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "smbd/smbd.h"
22 #include "smbd/globals.h"
23 #include "../libcli/auth/spnego.h"
24 #include "../auth/ntlmssp/ntlmssp.h"
25 #include "ntlmssp_wrap.h"
26 #include "../libcli/smb/smb_seal.h"
27 #include "../lib/util/asn1.h"
28 #include "auth.h"
29 #include "libsmb/libsmb.h"
30 #include "../lib/tsocket/tsocket.h"
31 #include "auth/gensec/gensec.h"
32
33 /******************************************************************************
34  Server side encryption.
35 ******************************************************************************/
36
37 /******************************************************************************
38  Return global enc context - this must change if we ever do multiple contexts.
39 ******************************************************************************/
40
41 static uint16_t srv_enc_ctx(const struct smb_trans_enc_state *es)
42 {
43         return es->enc_ctx_num;
44 }
45
46 /******************************************************************************
47  Is this an incoming encrypted packet ?
48 ******************************************************************************/
49
50 bool is_encrypted_packet(struct smbd_server_connection *sconn,
51                          const uint8_t *inbuf)
52 {
53         NTSTATUS status;
54         uint16_t enc_num;
55
56         /* Ignore non-session messages or non 0xFF'E' messages. */
57         if(CVAL(inbuf,0)
58            || (smb_len(inbuf) < 8)
59            || !(inbuf[4] == 0xFF && inbuf[5] == 'E')) {
60                 return false;
61         }
62
63         status = get_enc_ctx_num(inbuf, &enc_num);
64         if (!NT_STATUS_IS_OK(status)) {
65                 return false;
66         }
67
68         /* Encrypted messages are 0xFF'E'<ctx> */
69         if (srv_trans_enc_ctx && enc_num == srv_enc_ctx(srv_trans_enc_ctx)) {
70                 return true;
71         }
72         return false;
73 }
74
75 /******************************************************************************
76  Create an auth_ntlmssp_state and ensure pointer copy is correct.
77 ******************************************************************************/
78
79 static NTSTATUS make_auth_ntlmssp(const struct tsocket_address *remote_address,
80                                   struct smb_trans_enc_state *es)
81 {
82         struct auth_generic_state *auth_ntlmssp_state;
83         NTSTATUS status = auth_generic_prepare(remote_address,
84                                                &auth_ntlmssp_state);
85         if (!NT_STATUS_IS_OK(status)) {
86                 return nt_status_squash(status);
87         }
88
89         gensec_want_feature(auth_ntlmssp_state->gensec_security, GENSEC_FEATURE_SEAL);
90
91         status = auth_ntlmssp_start(auth_ntlmssp_state);
92
93         if (!NT_STATUS_IS_OK(status)) {
94                 TALLOC_FREE(auth_ntlmssp_state);
95                 return nt_status_squash(status);
96         }
97
98         /* We do not need the auth_ntlmssp layer any more, which was
99          * allocated on NULL, so promote gensec_security to the NULL
100          * context */
101         es->s.gensec_security = talloc_move(NULL, &auth_ntlmssp_state->gensec_security);
102         TALLOC_FREE(auth_ntlmssp_state);
103
104         return status;
105 }
106
107 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
108
109 /******************************************************************************
110  Import a name.
111 ******************************************************************************/
112
113 static NTSTATUS get_srv_gss_creds(const char *service,
114                                 const char *name,
115                                 gss_cred_usage_t cred_type,
116                                 gss_cred_id_t *p_srv_cred)
117 {
118         OM_uint32 ret;
119         OM_uint32 min;
120         gss_name_t srv_name;
121         gss_buffer_desc input_name;
122         char *host_princ_s = NULL;
123         NTSTATUS status = NT_STATUS_OK;
124
125         gss_OID_desc nt_hostbased_service =
126         {10, discard_const_p(char, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04")};
127
128         if (asprintf(&host_princ_s, "%s@%s", service, name) == -1) {
129                 return NT_STATUS_NO_MEMORY;
130         }
131
132         input_name.value = host_princ_s;
133         input_name.length = strlen(host_princ_s) + 1;
134
135         ret = gss_import_name(&min,
136                                 &input_name,
137                                 &nt_hostbased_service,
138                                 &srv_name);
139
140         DEBUG(10,("get_srv_gss_creds: imported name %s\n",
141                 host_princ_s ));
142
143         if (ret != GSS_S_COMPLETE) {
144                 SAFE_FREE(host_princ_s);
145                 return map_nt_error_from_gss(ret, min);
146         }
147
148         /*
149          * We're accessing the krb5.keytab file here.
150          * ensure we have permissions to do so.
151          */
152         become_root();
153
154         ret = gss_acquire_cred(&min,
155                                 srv_name,
156                                 GSS_C_INDEFINITE,
157                                 GSS_C_NULL_OID_SET,
158                                 cred_type,
159                                 p_srv_cred,
160                                 NULL,
161                                 NULL);
162         unbecome_root();
163
164         if (ret != GSS_S_COMPLETE) {
165                 ADS_STATUS adss = ADS_ERROR_GSS(ret, min);
166                 DEBUG(10,("get_srv_gss_creds: gss_acquire_cred failed with %s\n",
167                         ads_errstr(adss)));
168                 status = map_nt_error_from_gss(ret, min);
169         }
170
171         SAFE_FREE(host_princ_s);
172         gss_release_name(&min, &srv_name);
173         return status;
174 }
175
176 /******************************************************************************
177  Create a gss state.
178  Try and get the cifs/server@realm principal first, then fall back to
179  host/server@realm.
180 ******************************************************************************/
181
182 static NTSTATUS make_auth_gss(struct smb_trans_enc_state *es)
183 {
184         NTSTATUS status;
185         gss_cred_id_t srv_cred;
186         fstring fqdn;
187
188         name_to_fqdn(fqdn, lp_netbios_name());
189         strlower_m(fqdn);
190
191         status = get_srv_gss_creds("cifs", fqdn, GSS_C_ACCEPT, &srv_cred);
192         if (!NT_STATUS_IS_OK(status)) {
193                 status = get_srv_gss_creds("host", fqdn, GSS_C_ACCEPT, &srv_cred);
194                 if (!NT_STATUS_IS_OK(status)) {
195                         return nt_status_squash(status);
196                 }
197         }
198
199         es->s.gss_state = SMB_MALLOC_P(struct smb_tran_enc_state_gss);
200         if (!es->s.gss_state) {
201                 OM_uint32 min;
202                 gss_release_cred(&min, &srv_cred);
203                 return NT_STATUS_NO_MEMORY;
204         }
205         ZERO_STRUCTP(es->s.gss_state);
206         es->s.gss_state->creds = srv_cred;
207
208         /* No context yet. */
209         es->s.gss_state->gss_ctx = GSS_C_NO_CONTEXT;
210
211         return NT_STATUS_OK;
212 }
213 #endif
214
215 /******************************************************************************
216  Shutdown a server encryption context.
217 ******************************************************************************/
218
219 static void srv_free_encryption_context(struct smb_trans_enc_state **pp_es)
220 {
221         struct smb_trans_enc_state *es = *pp_es;
222
223         if (!es) {
224                 return;
225         }
226
227         common_free_encryption_state(&es);
228
229         SAFE_FREE(es);
230         *pp_es = NULL;
231 }
232
233 /******************************************************************************
234  Create a server encryption context.
235 ******************************************************************************/
236
237 static NTSTATUS make_srv_encryption_context(const struct tsocket_address *remote_address,
238                                             enum smb_trans_enc_type smb_enc_type,
239                                             struct smb_trans_enc_state **pp_es)
240 {
241         struct smb_trans_enc_state *es;
242
243         *pp_es = NULL;
244
245         ZERO_STRUCTP(partial_srv_trans_enc_ctx);
246         es = SMB_MALLOC_P(struct smb_trans_enc_state);
247         if (!es) {
248                 return NT_STATUS_NO_MEMORY;
249         }
250         ZERO_STRUCTP(es);
251         es->smb_enc_type = smb_enc_type;
252         switch (smb_enc_type) {
253                 case SMB_TRANS_ENC_NTLM:
254                         {
255                                 NTSTATUS status = make_auth_ntlmssp(remote_address,
256                                                                     es);
257                                 if (!NT_STATUS_IS_OK(status)) {
258                                         srv_free_encryption_context(&es);
259                                         return status;
260                                 }
261                         }
262                         break;
263
264 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
265                 case SMB_TRANS_ENC_GSS:
266                         /* Acquire our credentials by calling gss_acquire_cred here. */
267                         {
268                                 NTSTATUS status = make_auth_gss(es);
269                                 if (!NT_STATUS_IS_OK(status)) {
270                                         srv_free_encryption_context(&es);
271                                         return status;
272                                 }
273                         }
274                         break;
275 #endif
276                 default:
277                         srv_free_encryption_context(&es);
278                         return NT_STATUS_INVALID_PARAMETER;
279         }
280         *pp_es = es;
281         return NT_STATUS_OK;
282 }
283
284 /******************************************************************************
285  Free an encryption-allocated buffer.
286 ******************************************************************************/
287
288 void srv_free_enc_buffer(struct smbd_server_connection *sconn, char *buf)
289 {
290         /* We know this is an smb buffer, and we
291          * didn't malloc, only copy, for a keepalive,
292          * so ignore non-session messages. */
293
294         if(CVAL(buf,0)) {
295                 return;
296         }
297
298         if (srv_trans_enc_ctx) {
299                 common_free_enc_buffer(srv_trans_enc_ctx, buf);
300         }
301 }
302
303 /******************************************************************************
304  Decrypt an incoming buffer.
305 ******************************************************************************/
306
307 NTSTATUS srv_decrypt_buffer(struct smbd_server_connection *sconn, char *buf)
308 {
309         /* Ignore non-session messages. */
310         if(CVAL(buf,0)) {
311                 return NT_STATUS_OK;
312         }
313
314         if (srv_trans_enc_ctx) {
315                 return common_decrypt_buffer(srv_trans_enc_ctx, buf);
316         }
317
318         return NT_STATUS_OK;
319 }
320
321 /******************************************************************************
322  Encrypt an outgoing buffer. Return the encrypted pointer in buf_out.
323 ******************************************************************************/
324
325 NTSTATUS srv_encrypt_buffer(struct smbd_server_connection *sconn, char *buf,
326                             char **buf_out)
327 {
328         *buf_out = buf;
329
330         /* Ignore non-session messages. */
331         if(CVAL(buf,0)) {
332                 return NT_STATUS_OK;
333         }
334
335         if (srv_trans_enc_ctx) {
336                 return common_encrypt_buffer(srv_trans_enc_ctx, buf, buf_out);
337         }
338         /* Not encrypting. */
339         return NT_STATUS_OK;
340 }
341
342 /******************************************************************************
343  Do the gss encryption negotiation. Parameters are in/out.
344  Until success we do everything on the partial enc ctx.
345 ******************************************************************************/
346
347 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
348 static NTSTATUS srv_enc_spnego_gss_negotiate(const struct tsocket_address *remote_address,
349                                              unsigned char **ppdata,
350                                              size_t *p_data_size,
351                                              DATA_BLOB secblob)
352 {
353         OM_uint32 ret;
354         OM_uint32 min;
355         OM_uint32 flags = 0;
356         gss_buffer_desc in_buf, out_buf;
357         struct smb_tran_enc_state_gss *gss_state;
358         DATA_BLOB auth_reply = data_blob_null;
359         DATA_BLOB response = data_blob_null;
360         NTSTATUS status;
361
362         if (!partial_srv_trans_enc_ctx) {
363                 status = make_srv_encryption_context(remote_address,
364                                                      SMB_TRANS_ENC_GSS,
365                                                      &partial_srv_trans_enc_ctx);
366                 if (!NT_STATUS_IS_OK(status)) {
367                         return status;
368                 }
369         }
370
371         gss_state = partial_srv_trans_enc_ctx->s.gss_state;
372
373         in_buf.value = secblob.data;
374         in_buf.length = secblob.length;
375
376         out_buf.value = NULL;
377         out_buf.length = 0;
378
379         become_root();
380
381         ret = gss_accept_sec_context(&min,
382                                 &gss_state->gss_ctx,
383                                 gss_state->creds,
384                                 &in_buf,
385                                 GSS_C_NO_CHANNEL_BINDINGS,
386                                 NULL,
387                                 NULL,           /* Ignore oids. */
388                                 &out_buf,       /* To return. */
389                                 &flags,
390                                 NULL,           /* Ingore time. */
391                                 NULL);          /* Ignore delegated creds. */
392         unbecome_root();
393
394         status = gss_err_to_ntstatus(ret, min);
395         if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) {
396                 return status;
397         }
398
399         /* Ensure we've got sign+seal available. */
400         if (ret == GSS_S_COMPLETE) {
401                 if ((flags & (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) !=
402                                 (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) {
403                         DEBUG(0,("srv_enc_spnego_gss_negotiate: quality of service not good enough "
404                                 "for SMB sealing.\n"));
405                         gss_release_buffer(&min, &out_buf);
406                         return NT_STATUS_ACCESS_DENIED;
407                 }
408         }
409
410         auth_reply = data_blob(out_buf.value, out_buf.length);
411         gss_release_buffer(&min, &out_buf);
412
413         /* Wrap in SPNEGO. */
414         response = spnego_gen_auth_response(talloc_tos(), &auth_reply, status, OID_KERBEROS5);
415         data_blob_free(&auth_reply);
416
417         SAFE_FREE(*ppdata);
418         *ppdata = (unsigned char *)memdup(response.data, response.length);
419         if ((*ppdata) == NULL && response.length > 0) {
420                 status = NT_STATUS_NO_MEMORY;
421         }
422         *p_data_size = response.length;
423
424         data_blob_free(&response);
425
426         return status;
427 }
428 #endif
429
430 /******************************************************************************
431  Do the NTLM SPNEGO (or raw) encryption negotiation. Parameters are in/out.
432  Until success we do everything on the partial enc ctx.
433 ******************************************************************************/
434
435 static NTSTATUS srv_enc_ntlm_negotiate(const struct tsocket_address *remote_address,
436                                        unsigned char **ppdata,
437                                        size_t *p_data_size,
438                                        DATA_BLOB secblob,
439                                        bool spnego_wrap)
440 {
441         NTSTATUS status;
442         DATA_BLOB chal = data_blob_null;
443         DATA_BLOB response = data_blob_null;
444
445         status = make_srv_encryption_context(remote_address,
446                                              SMB_TRANS_ENC_NTLM,
447                                              &partial_srv_trans_enc_ctx);
448         if (!NT_STATUS_IS_OK(status)) {
449                 return status;
450         }
451
452         status = gensec_update(partial_srv_trans_enc_ctx->s.gensec_security,
453                                talloc_tos(), NULL,
454                                secblob, &chal);
455
456         /* status here should be NT_STATUS_MORE_PROCESSING_REQUIRED
457          * for success ... */
458
459         if (spnego_wrap) {
460                 response = spnego_gen_auth_response(talloc_tos(), &chal, status, OID_NTLMSSP);
461                 data_blob_free(&chal);
462         } else {
463                 /* Return the raw blob. */
464                 response = chal;
465         }
466
467         SAFE_FREE(*ppdata);
468         *ppdata = (unsigned char *)memdup(response.data, response.length);
469         if ((*ppdata) == NULL && response.length > 0) {
470                 status = NT_STATUS_NO_MEMORY;
471         }
472         *p_data_size = response.length;
473         data_blob_free(&response);
474
475         return status;
476 }
477
478 /******************************************************************************
479  Do the SPNEGO encryption negotiation. Parameters are in/out.
480  Based off code in smbd/sesssionsetup.c
481  Until success we do everything on the partial enc ctx.
482 ******************************************************************************/
483
484 static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn,
485                                         unsigned char **ppdata,
486                                         size_t *p_data_size,
487                                         unsigned char **pparam,
488                                         size_t *p_param_size)
489 {
490         NTSTATUS status;
491         DATA_BLOB blob = data_blob_null;
492         DATA_BLOB secblob = data_blob_null;
493         char *kerb_mech = NULL;
494
495         blob = data_blob_const(*ppdata, *p_data_size);
496
497         status = parse_spnego_mechanisms(talloc_tos(), blob, &secblob, &kerb_mech);
498         if (!NT_STATUS_IS_OK(status)) {
499                 return nt_status_squash(status);
500         }
501
502         /* We should have no partial context at this point. */
503
504         srv_free_encryption_context(&partial_srv_trans_enc_ctx);
505
506         if (kerb_mech) {
507                 TALLOC_FREE(kerb_mech);
508
509 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
510                 status = srv_enc_spnego_gss_negotiate(conn->sconn->remote_address,
511                                                       ppdata,
512                                                       p_data_size,
513                                                       secblob);
514 #else
515                 /* Currently we don't SPNEGO negotiate
516                  * back to NTLMSSP as we do in sessionsetupX. We should... */
517                 return NT_STATUS_LOGON_FAILURE;
518 #endif
519         } else {
520                 status = srv_enc_ntlm_negotiate(conn->sconn->remote_address,
521                                                 ppdata,
522                                                 p_data_size,
523                                                 secblob,
524                                                 true);
525         }
526
527         data_blob_free(&secblob);
528
529         if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
530                 srv_free_encryption_context(&partial_srv_trans_enc_ctx);
531                 return nt_status_squash(status);
532         }
533
534         if (NT_STATUS_IS_OK(status)) {
535                 /* Return the context we're using for this encryption state. */
536                 if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) {
537                         return NT_STATUS_NO_MEMORY;
538                 }
539                 SSVAL(*pparam,0,partial_srv_trans_enc_ctx->enc_ctx_num);
540                 *p_param_size = 2;
541         }
542
543         return status;
544 }
545
546 /******************************************************************************
547  Complete a SPNEGO encryption negotiation. Parameters are in/out.
548  We only get this for a NTLM auth second stage.
549 ******************************************************************************/
550
551 static NTSTATUS srv_enc_spnego_ntlm_auth(connection_struct *conn,
552                                         unsigned char **ppdata,
553                                         size_t *p_data_size,
554                                         unsigned char **pparam,
555                                         size_t *p_param_size)
556 {
557         NTSTATUS status;
558         DATA_BLOB blob = data_blob_null;
559         DATA_BLOB auth = data_blob_null;
560         DATA_BLOB auth_reply = data_blob_null;
561         DATA_BLOB response = data_blob_null;
562         struct smb_trans_enc_state *es = partial_srv_trans_enc_ctx;
563
564         /* We must have a partial context here. */
565
566         if (!es || es->s.gensec_security == NULL || es->smb_enc_type != SMB_TRANS_ENC_NTLM) {
567                 srv_free_encryption_context(&partial_srv_trans_enc_ctx);
568                 return NT_STATUS_INVALID_PARAMETER;
569         }
570
571         blob = data_blob_const(*ppdata, *p_data_size);
572         if (!spnego_parse_auth(talloc_tos(), blob, &auth)) {
573                 srv_free_encryption_context(&partial_srv_trans_enc_ctx);
574                 return NT_STATUS_INVALID_PARAMETER;
575         }
576
577         status = gensec_update(es->s.gensec_security, talloc_tos(), NULL, auth, &auth_reply);
578         data_blob_free(&auth);
579
580         /* From RFC4178.
581          *
582          *    supportedMech
583          *
584          *          This field SHALL only be present in the first reply from the
585          *                target.
586          * So set mechOID to NULL here.
587          */
588
589         response = spnego_gen_auth_response(talloc_tos(), &auth_reply, status, NULL);
590         data_blob_free(&auth_reply);
591
592         if (NT_STATUS_IS_OK(status)) {
593                 /* Return the context we're using for this encryption state. */
594                 if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) {
595                         return NT_STATUS_NO_MEMORY;
596                 }
597                 SSVAL(*pparam,0,es->enc_ctx_num);
598                 *p_param_size = 2;
599         }
600
601         SAFE_FREE(*ppdata);
602         *ppdata = (unsigned char *)memdup(response.data, response.length);
603         if ((*ppdata) == NULL && response.length > 0)
604                 return NT_STATUS_NO_MEMORY;
605         *p_data_size = response.length;
606         data_blob_free(&response);
607         return status;
608 }
609
610 /******************************************************************************
611  Raw NTLM encryption negotiation. Parameters are in/out.
612  This function does both steps.
613 ******************************************************************************/
614
615 static NTSTATUS srv_enc_raw_ntlm_auth(connection_struct *conn,
616                                         unsigned char **ppdata,
617                                         size_t *p_data_size,
618                                         unsigned char **pparam,
619                                         size_t *p_param_size)
620 {
621         NTSTATUS status;
622         DATA_BLOB blob = data_blob_const(*ppdata, *p_data_size);
623         DATA_BLOB response = data_blob_null;
624         struct smb_trans_enc_state *es;
625
626         if (!partial_srv_trans_enc_ctx) {
627                 /* This is the initial step. */
628                 status = srv_enc_ntlm_negotiate(conn->sconn->remote_address,
629                                                 ppdata,
630                                                 p_data_size,
631                                                 blob,
632                                                 false);
633                 if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
634                         srv_free_encryption_context(&partial_srv_trans_enc_ctx);
635                         return nt_status_squash(status);
636                 }
637                 return status;
638         }
639
640         es = partial_srv_trans_enc_ctx;
641         if (!es || es->s.gensec_security == NULL || es->smb_enc_type != SMB_TRANS_ENC_NTLM) {
642                 srv_free_encryption_context(&partial_srv_trans_enc_ctx);
643                 return NT_STATUS_INVALID_PARAMETER;
644         }
645
646         /* Second step. */
647         status = gensec_update(partial_srv_trans_enc_ctx->s.gensec_security,
648                                talloc_tos(), NULL,
649                                blob, &response);
650
651         if (NT_STATUS_IS_OK(status)) {
652                 /* Return the context we're using for this encryption state. */
653                 if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) {
654                         return NT_STATUS_NO_MEMORY;
655                 }
656                 SSVAL(*pparam, 0, es->enc_ctx_num);
657                 *p_param_size = 2;
658         }
659
660         /* Return the raw blob. */
661         SAFE_FREE(*ppdata);
662         *ppdata = (unsigned char *)memdup(response.data, response.length);
663         if ((*ppdata) == NULL && response.length > 0)
664                 return NT_STATUS_NO_MEMORY;
665         *p_data_size = response.length;
666         data_blob_free(&response);
667         return status;
668 }
669
670 /******************************************************************************
671  Do the SPNEGO encryption negotiation. Parameters are in/out.
672 ******************************************************************************/
673
674 NTSTATUS srv_request_encryption_setup(connection_struct *conn,
675                                         unsigned char **ppdata,
676                                         size_t *p_data_size,
677                                         unsigned char **pparam,
678                                         size_t *p_param_size)
679 {
680         unsigned char *pdata = *ppdata;
681
682         SAFE_FREE(*pparam);
683         *p_param_size = 0;
684
685         if (*p_data_size < 1) {
686                 return NT_STATUS_INVALID_PARAMETER;
687         }
688
689         if (pdata[0] == ASN1_APPLICATION(0)) {
690                 /* its a negTokenTarg packet */
691                 return srv_enc_spnego_negotiate(conn, ppdata, p_data_size, pparam, p_param_size);
692         }
693
694         if (pdata[0] == ASN1_CONTEXT(1)) {
695                 /* It's an auth packet */
696                 return srv_enc_spnego_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size);
697         }
698
699         /* Maybe it's a raw unwrapped auth ? */
700         if (*p_data_size < 7) {
701                 return NT_STATUS_INVALID_PARAMETER;
702         }
703
704         if (strncmp((char *)pdata, "NTLMSSP", 7) == 0) {
705                 return srv_enc_raw_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size);
706         }
707
708         DEBUG(1,("srv_request_encryption_setup: Unknown packet\n"));
709
710         return NT_STATUS_LOGON_FAILURE;
711 }
712
713 /******************************************************************************
714  Negotiation was successful - turn on server-side encryption.
715 ******************************************************************************/
716
717 static NTSTATUS check_enc_good(struct smb_trans_enc_state *es)
718 {
719         if (!es) {
720                 return NT_STATUS_LOGON_FAILURE;
721         }
722
723         if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
724                 if (!gensec_have_feature(es->s.gensec_security, GENSEC_FEATURE_SIGN)) {
725                         return NT_STATUS_INVALID_PARAMETER;
726                 }
727
728                 if (!gensec_have_feature(es->s.gensec_security, GENSEC_FEATURE_SEAL)) {
729                         return NT_STATUS_INVALID_PARAMETER;
730                 }
731         }
732         /* Todo - check gssapi case. */
733
734         return NT_STATUS_OK;
735 }
736
737 /******************************************************************************
738  Negotiation was successful - turn on server-side encryption.
739 ******************************************************************************/
740
741 NTSTATUS srv_encryption_start(connection_struct *conn)
742 {
743         NTSTATUS status;
744
745         /* Check that we are really doing sign+seal. */
746         status = check_enc_good(partial_srv_trans_enc_ctx);
747         if (!NT_STATUS_IS_OK(status)) {
748                 return status;
749         }
750         /* Throw away the context we're using currently (if any). */
751         srv_free_encryption_context(&srv_trans_enc_ctx);
752
753         /* Steal the partial pointer. Deliberate shallow copy. */
754         srv_trans_enc_ctx = partial_srv_trans_enc_ctx;
755         srv_trans_enc_ctx->enc_on = true;
756
757         partial_srv_trans_enc_ctx = NULL;
758
759         DEBUG(1,("srv_encryption_start: context negotiated\n"));
760         return NT_STATUS_OK;
761 }
762
763 /******************************************************************************
764  Shutdown all server contexts.
765 ******************************************************************************/
766
767 void server_encryption_shutdown(struct smbd_server_connection *sconn)
768 {
769         srv_free_encryption_context(&partial_srv_trans_enc_ctx);
770         srv_free_encryption_context(&srv_trans_enc_ctx);
771 }