2 Unix SMB/CIFS implementation.
3 SMB Transport encryption (sealing) code - server code.
4 Copyright (C) Jeremy Allison 2007.
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.
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.
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/>.
21 #include "smbd/globals.h"
22 #include "../libcli/auth/spnego.h"
23 #include "../libcli/auth/ntlmssp.h"
24 #include "ntlmssp_wrap.h"
25 #include "smb_crypt.h"
27 /******************************************************************************
28 Server side encryption.
29 ******************************************************************************/
31 /******************************************************************************
33 ******************************************************************************/
35 struct smb_srv_trans_enc_ctx {
36 struct smb_trans_enc_state *es;
37 struct auth_ntlmssp_state *auth_ntlmssp_state; /* Must be kept in sync with pointer in ec->ntlmssp_state. */
40 /******************************************************************************
41 Return global enc context - this must change if we ever do multiple contexts.
42 ******************************************************************************/
44 uint16_t srv_enc_ctx(void)
46 return srv_trans_enc_ctx->es->enc_ctx_num;
49 /******************************************************************************
50 Is this an incoming encrypted packet ?
51 ******************************************************************************/
53 bool is_encrypted_packet(const uint8_t *inbuf)
58 /* Ignore non-session messages or non 0xFF'E' messages. */
60 || (smb_len(inbuf) < 8)
61 || !(inbuf[4] == 0xFF && inbuf[5] == 'E')) {
65 status = get_enc_ctx_num(inbuf, &enc_num);
66 if (!NT_STATUS_IS_OK(status)) {
70 /* Encrypted messages are 0xFF'E'<ctx> */
71 if (srv_trans_enc_ctx && enc_num == srv_enc_ctx()) {
77 /******************************************************************************
78 Create an auth_ntlmssp_state and ensure pointer copy is correct.
79 ******************************************************************************/
81 static NTSTATUS make_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec)
83 NTSTATUS status = auth_ntlmssp_start(&ec->auth_ntlmssp_state);
84 if (!NT_STATUS_IS_OK(status)) {
85 return nt_status_squash(status);
89 * We must remember to update the pointer copy for the common
90 * functions after any auth_ntlmssp_start/auth_ntlmssp_end.
92 ec->es->s.ntlmssp_state = auth_ntlmssp_get_ntlmssp_state(ec->auth_ntlmssp_state);
96 /******************************************************************************
97 Destroy an auth_ntlmssp_state and ensure pointer copy is correct.
98 ******************************************************************************/
100 static void destroy_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec)
103 * We must remember to update the pointer copy for the common
104 * functions after any auth_ntlmssp_start/auth_ntlmssp_end.
107 if (ec->auth_ntlmssp_state) {
108 TALLOC_FREE(ec->auth_ntlmssp_state);
109 /* The auth_ntlmssp_end killed this already. */
110 ec->es->s.ntlmssp_state = NULL;
114 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
116 /******************************************************************************
118 ******************************************************************************/
120 static NTSTATUS get_srv_gss_creds(const char *service,
122 gss_cred_usage_t cred_type,
123 gss_cred_id_t *p_srv_cred)
128 gss_buffer_desc input_name;
129 char *host_princ_s = NULL;
130 NTSTATUS status = NT_STATUS_OK;
132 gss_OID_desc nt_hostbased_service =
133 {10, CONST_DISCARD(char *,"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04")};
135 if (asprintf(&host_princ_s, "%s@%s", service, name) == -1) {
136 return NT_STATUS_NO_MEMORY;
139 input_name.value = host_princ_s;
140 input_name.length = strlen(host_princ_s) + 1;
142 ret = gss_import_name(&min,
144 &nt_hostbased_service,
147 DEBUG(10,("get_srv_gss_creds: imported name %s\n",
150 if (ret != GSS_S_COMPLETE) {
151 SAFE_FREE(host_princ_s);
152 return map_nt_error_from_gss(ret, min);
156 * We're accessing the krb5.keytab file here.
157 * ensure we have permissions to do so.
161 ret = gss_acquire_cred(&min,
171 if (ret != GSS_S_COMPLETE) {
172 ADS_STATUS adss = ADS_ERROR_GSS(ret, min);
173 DEBUG(10,("get_srv_gss_creds: gss_acquire_cred failed with %s\n",
175 status = map_nt_error_from_gss(ret, min);
178 SAFE_FREE(host_princ_s);
179 gss_release_name(&min, &srv_name);
183 /******************************************************************************
185 Try and get the cifs/server@realm principal first, then fall back to
187 ******************************************************************************/
189 static NTSTATUS make_auth_gss(struct smb_srv_trans_enc_ctx *ec)
192 gss_cred_id_t srv_cred;
195 name_to_fqdn(fqdn, global_myname());
198 status = get_srv_gss_creds("cifs", fqdn, GSS_C_ACCEPT, &srv_cred);
199 if (!NT_STATUS_IS_OK(status)) {
200 status = get_srv_gss_creds("host", fqdn, GSS_C_ACCEPT, &srv_cred);
201 if (!NT_STATUS_IS_OK(status)) {
202 return nt_status_squash(status);
206 ec->es->s.gss_state = SMB_MALLOC_P(struct smb_tran_enc_state_gss);
207 if (!ec->es->s.gss_state) {
209 gss_release_cred(&min, &srv_cred);
210 return NT_STATUS_NO_MEMORY;
212 ZERO_STRUCTP(ec->es->s.gss_state);
213 ec->es->s.gss_state->creds = srv_cred;
215 /* No context yet. */
216 ec->es->s.gss_state->gss_ctx = GSS_C_NO_CONTEXT;
222 /******************************************************************************
223 Shutdown a server encryption context.
224 ******************************************************************************/
226 static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec)
228 struct smb_srv_trans_enc_ctx *ec = *pp_ec;
235 switch (ec->es->smb_enc_type) {
236 case SMB_TRANS_ENC_NTLM:
237 destroy_auth_ntlmssp(ec);
239 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
240 case SMB_TRANS_ENC_GSS:
244 common_free_encryption_state(&ec->es);
251 /******************************************************************************
252 Create a server encryption context.
253 ******************************************************************************/
255 static NTSTATUS make_srv_encryption_context(enum smb_trans_enc_type smb_enc_type, struct smb_srv_trans_enc_ctx **pp_ec)
257 struct smb_srv_trans_enc_ctx *ec;
261 ec = SMB_MALLOC_P(struct smb_srv_trans_enc_ctx);
263 return NT_STATUS_NO_MEMORY;
265 ZERO_STRUCTP(partial_srv_trans_enc_ctx);
266 ec->es = SMB_MALLOC_P(struct smb_trans_enc_state);
269 return NT_STATUS_NO_MEMORY;
271 ZERO_STRUCTP(ec->es);
272 ec->es->smb_enc_type = smb_enc_type;
273 switch (smb_enc_type) {
274 case SMB_TRANS_ENC_NTLM:
276 NTSTATUS status = make_auth_ntlmssp(ec);
277 if (!NT_STATUS_IS_OK(status)) {
278 srv_free_encryption_context(&ec);
284 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
285 case SMB_TRANS_ENC_GSS:
286 /* Acquire our credentials by calling gss_acquire_cred here. */
288 NTSTATUS status = make_auth_gss(ec);
289 if (!NT_STATUS_IS_OK(status)) {
290 srv_free_encryption_context(&ec);
297 srv_free_encryption_context(&ec);
298 return NT_STATUS_INVALID_PARAMETER;
304 /******************************************************************************
305 Free an encryption-allocated buffer.
306 ******************************************************************************/
308 void srv_free_enc_buffer(char *buf)
310 /* We know this is an smb buffer, and we
311 * didn't malloc, only copy, for a keepalive,
312 * so ignore non-session messages. */
318 if (srv_trans_enc_ctx) {
319 common_free_enc_buffer(srv_trans_enc_ctx->es, buf);
323 /******************************************************************************
324 Decrypt an incoming buffer.
325 ******************************************************************************/
327 NTSTATUS srv_decrypt_buffer(char *buf)
329 /* Ignore non-session messages. */
334 if (srv_trans_enc_ctx) {
335 return common_decrypt_buffer(srv_trans_enc_ctx->es, buf);
341 /******************************************************************************
342 Encrypt an outgoing buffer. Return the encrypted pointer in buf_out.
343 ******************************************************************************/
345 NTSTATUS srv_encrypt_buffer(char *buf, char **buf_out)
349 /* Ignore non-session messages. */
354 if (srv_trans_enc_ctx) {
355 return common_encrypt_buffer(srv_trans_enc_ctx->es, buf, buf_out);
357 /* Not encrypting. */
361 /******************************************************************************
362 Do the gss encryption negotiation. Parameters are in/out.
363 Until success we do everything on the partial enc ctx.
364 ******************************************************************************/
366 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
367 static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob)
372 gss_buffer_desc in_buf, out_buf;
373 struct smb_tran_enc_state_gss *gss_state;
374 DATA_BLOB auth_reply = data_blob_null;
375 DATA_BLOB response = data_blob_null;
378 if (!partial_srv_trans_enc_ctx) {
379 status = make_srv_encryption_context(SMB_TRANS_ENC_GSS, &partial_srv_trans_enc_ctx);
380 if (!NT_STATUS_IS_OK(status)) {
385 gss_state = partial_srv_trans_enc_ctx->es->s.gss_state;
387 in_buf.value = secblob.data;
388 in_buf.length = secblob.length;
390 out_buf.value = NULL;
395 ret = gss_accept_sec_context(&min,
399 GSS_C_NO_CHANNEL_BINDINGS,
401 NULL, /* Ignore oids. */
402 &out_buf, /* To return. */
404 NULL, /* Ingore time. */
405 NULL); /* Ignore delegated creds. */
408 status = gss_err_to_ntstatus(ret, min);
409 if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) {
413 /* Ensure we've got sign+seal available. */
414 if (ret == GSS_S_COMPLETE) {
415 if ((flags & (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) !=
416 (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) {
417 DEBUG(0,("srv_enc_spnego_gss_negotiate: quality of service not good enough "
418 "for SMB sealing.\n"));
419 gss_release_buffer(&min, &out_buf);
420 return NT_STATUS_ACCESS_DENIED;
424 auth_reply = data_blob(out_buf.value, out_buf.length);
425 gss_release_buffer(&min, &out_buf);
427 /* Wrap in SPNEGO. */
428 response = spnego_gen_auth_response(talloc_tos(), &auth_reply, status, OID_KERBEROS5);
429 data_blob_free(&auth_reply);
432 *ppdata = (unsigned char *)memdup(response.data, response.length);
433 if ((*ppdata) == NULL && response.length > 0) {
434 status = NT_STATUS_NO_MEMORY;
436 *p_data_size = response.length;
438 data_blob_free(&response);
444 /******************************************************************************
445 Do the NTLM SPNEGO (or raw) encryption negotiation. Parameters are in/out.
446 Until success we do everything on the partial enc ctx.
447 ******************************************************************************/
449 static NTSTATUS srv_enc_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob, bool spnego_wrap)
452 DATA_BLOB chal = data_blob_null;
453 DATA_BLOB response = data_blob_null;
455 status = make_srv_encryption_context(SMB_TRANS_ENC_NTLM, &partial_srv_trans_enc_ctx);
456 if (!NT_STATUS_IS_OK(status)) {
460 status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, secblob, &chal);
462 /* status here should be NT_STATUS_MORE_PROCESSING_REQUIRED
466 response = spnego_gen_auth_response(talloc_tos(), &chal, status, OID_NTLMSSP);
467 data_blob_free(&chal);
469 /* Return the raw blob. */
474 *ppdata = (unsigned char *)memdup(response.data, response.length);
475 if ((*ppdata) == NULL && response.length > 0) {
476 status = NT_STATUS_NO_MEMORY;
478 *p_data_size = response.length;
479 data_blob_free(&response);
484 /******************************************************************************
485 Do the SPNEGO encryption negotiation. Parameters are in/out.
486 Based off code in smbd/sesssionsetup.c
487 Until success we do everything on the partial enc ctx.
488 ******************************************************************************/
490 static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn,
491 unsigned char **ppdata,
493 unsigned char **pparam,
494 size_t *p_param_size)
497 DATA_BLOB blob = data_blob_null;
498 DATA_BLOB secblob = data_blob_null;
499 char *kerb_mech = NULL;
501 blob = data_blob_const(*ppdata, *p_data_size);
503 status = parse_spnego_mechanisms(talloc_tos(), blob, &secblob, &kerb_mech);
504 if (!NT_STATUS_IS_OK(status)) {
505 return nt_status_squash(status);
508 /* We should have no partial context at this point. */
510 srv_free_encryption_context(&partial_srv_trans_enc_ctx);
513 TALLOC_FREE(kerb_mech);
515 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
516 status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob);
518 /* Currently we don't SPNEGO negotiate
519 * back to NTLMSSP as we do in sessionsetupX. We should... */
520 return NT_STATUS_LOGON_FAILURE;
523 status = srv_enc_ntlm_negotiate(ppdata, p_data_size, secblob, true);
526 data_blob_free(&secblob);
528 if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
529 srv_free_encryption_context(&partial_srv_trans_enc_ctx);
530 return nt_status_squash(status);
533 if (NT_STATUS_IS_OK(status)) {
534 /* Return the context we're using for this encryption state. */
535 if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) {
536 return NT_STATUS_NO_MEMORY;
538 SSVAL(*pparam,0,partial_srv_trans_enc_ctx->es->enc_ctx_num);
545 /******************************************************************************
546 Complete a SPNEGO encryption negotiation. Parameters are in/out.
547 We only get this for a NTLM auth second stage.
548 ******************************************************************************/
550 static NTSTATUS srv_enc_spnego_ntlm_auth(connection_struct *conn,
551 unsigned char **ppdata,
553 unsigned char **pparam,
554 size_t *p_param_size)
557 DATA_BLOB blob = data_blob_null;
558 DATA_BLOB auth = data_blob_null;
559 DATA_BLOB auth_reply = data_blob_null;
560 DATA_BLOB response = data_blob_null;
561 struct smb_srv_trans_enc_ctx *ec = partial_srv_trans_enc_ctx;
563 /* We must have a partial context here. */
565 if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) {
566 srv_free_encryption_context(&partial_srv_trans_enc_ctx);
567 return NT_STATUS_INVALID_PARAMETER;
570 blob = data_blob_const(*ppdata, *p_data_size);
571 if (!spnego_parse_auth(talloc_tos(), blob, &auth)) {
572 srv_free_encryption_context(&partial_srv_trans_enc_ctx);
573 return NT_STATUS_INVALID_PARAMETER;
576 status = auth_ntlmssp_update(ec->auth_ntlmssp_state, auth, &auth_reply);
577 data_blob_free(&auth);
583 * This field SHALL only be present in the first reply from the
585 * So set mechOID to NULL here.
588 response = spnego_gen_auth_response(talloc_tos(), &auth_reply, status, NULL);
589 data_blob_free(&auth_reply);
591 if (NT_STATUS_IS_OK(status)) {
592 /* Return the context we're using for this encryption state. */
593 if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) {
594 return NT_STATUS_NO_MEMORY;
596 SSVAL(*pparam,0,ec->es->enc_ctx_num);
601 *ppdata = (unsigned char *)memdup(response.data, response.length);
602 if ((*ppdata) == NULL && response.length > 0)
603 return NT_STATUS_NO_MEMORY;
604 *p_data_size = response.length;
605 data_blob_free(&response);
609 /******************************************************************************
610 Raw NTLM encryption negotiation. Parameters are in/out.
611 This function does both steps.
612 ******************************************************************************/
614 static NTSTATUS srv_enc_raw_ntlm_auth(connection_struct *conn,
615 unsigned char **ppdata,
617 unsigned char **pparam,
618 size_t *p_param_size)
621 DATA_BLOB blob = data_blob_const(*ppdata, *p_data_size);
622 DATA_BLOB response = data_blob_null;
623 struct smb_srv_trans_enc_ctx *ec;
625 if (!partial_srv_trans_enc_ctx) {
626 /* This is the initial step. */
627 status = srv_enc_ntlm_negotiate(ppdata, p_data_size, blob, false);
628 if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
629 srv_free_encryption_context(&partial_srv_trans_enc_ctx);
630 return nt_status_squash(status);
635 ec = partial_srv_trans_enc_ctx;
636 if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) {
637 srv_free_encryption_context(&partial_srv_trans_enc_ctx);
638 return NT_STATUS_INVALID_PARAMETER;
642 status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, blob, &response);
644 if (NT_STATUS_IS_OK(status)) {
645 /* Return the context we're using for this encryption state. */
646 if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) {
647 return NT_STATUS_NO_MEMORY;
649 SSVAL(*pparam,0,ec->es->enc_ctx_num);
653 /* Return the raw blob. */
655 *ppdata = (unsigned char *)memdup(response.data, response.length);
656 if ((*ppdata) == NULL && response.length > 0)
657 return NT_STATUS_NO_MEMORY;
658 *p_data_size = response.length;
659 data_blob_free(&response);
663 /******************************************************************************
664 Do the SPNEGO encryption negotiation. Parameters are in/out.
665 ******************************************************************************/
667 NTSTATUS srv_request_encryption_setup(connection_struct *conn,
668 unsigned char **ppdata,
670 unsigned char **pparam,
671 size_t *p_param_size)
673 unsigned char *pdata = *ppdata;
678 if (*p_data_size < 1) {
679 return NT_STATUS_INVALID_PARAMETER;
682 if (pdata[0] == ASN1_APPLICATION(0)) {
683 /* its a negTokenTarg packet */
684 return srv_enc_spnego_negotiate(conn, ppdata, p_data_size, pparam, p_param_size);
687 if (pdata[0] == ASN1_CONTEXT(1)) {
688 /* It's an auth packet */
689 return srv_enc_spnego_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size);
692 /* Maybe it's a raw unwrapped auth ? */
693 if (*p_data_size < 7) {
694 return NT_STATUS_INVALID_PARAMETER;
697 if (strncmp((char *)pdata, "NTLMSSP", 7) == 0) {
698 return srv_enc_raw_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size);
701 DEBUG(1,("srv_request_encryption_setup: Unknown packet\n"));
703 return NT_STATUS_LOGON_FAILURE;
706 /******************************************************************************
707 Negotiation was successful - turn on server-side encryption.
708 ******************************************************************************/
710 static NTSTATUS check_enc_good(struct smb_srv_trans_enc_ctx *ec)
712 if (!ec || !ec->es) {
713 return NT_STATUS_LOGON_FAILURE;
716 if (ec->es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
717 if (!auth_ntlmssp_negotiated_sign((ec->auth_ntlmssp_state))) {
718 return NT_STATUS_INVALID_PARAMETER;
721 if (!auth_ntlmssp_negotiated_seal((ec->auth_ntlmssp_state))) {
722 return NT_STATUS_INVALID_PARAMETER;
725 /* Todo - check gssapi case. */
730 /******************************************************************************
731 Negotiation was successful - turn on server-side encryption.
732 ******************************************************************************/
734 NTSTATUS srv_encryption_start(connection_struct *conn)
738 /* Check that we are really doing sign+seal. */
739 status = check_enc_good(partial_srv_trans_enc_ctx);
740 if (!NT_STATUS_IS_OK(status)) {
743 /* Throw away the context we're using currently (if any). */
744 srv_free_encryption_context(&srv_trans_enc_ctx);
746 /* Steal the partial pointer. Deliberate shallow copy. */
747 srv_trans_enc_ctx = partial_srv_trans_enc_ctx;
748 srv_trans_enc_ctx->es->enc_on = true;
750 partial_srv_trans_enc_ctx = NULL;
752 DEBUG(1,("srv_encryption_start: context negotiated\n"));
756 /******************************************************************************
757 Shutdown all server contexts.
758 ******************************************************************************/
760 void server_encryption_shutdown(void)
762 srv_free_encryption_context(&partial_srv_trans_enc_ctx);
763 srv_free_encryption_context(&srv_trans_enc_ctx);