@@ -433,6 +433,29 @@ build_compression_ctxt(struct smb2_compression_capabilities_context *pneg_ctxt)
433433 pneg_ctxt -> CompressionAlgorithms [2 ] = SMB3_COMPRESS_LZNT1 ;
434434}
435435
436+ static unsigned int
437+ build_signing_ctxt (struct smb2_signing_capabilities * pneg_ctxt )
438+ {
439+ unsigned int ctxt_len = sizeof (struct smb2_signing_capabilities );
440+ unsigned short num_algs = 1 ; /* number of signing algorithms sent */
441+
442+ pneg_ctxt -> ContextType = SMB2_SIGNING_CAPABILITIES ;
443+ /*
444+ * Context Data length must be rounded to multiple of 8 for some servers
445+ */
446+ pneg_ctxt -> DataLength = cpu_to_le16 (DIV_ROUND_UP (
447+ sizeof (struct smb2_signing_capabilities ) -
448+ sizeof (struct smb2_neg_context ) +
449+ (num_algs * 2 /* sizeof u16 */ ), 8 ) * 8 );
450+ pneg_ctxt -> SigningAlgorithmCount = cpu_to_le16 (num_algs );
451+ pneg_ctxt -> SigningAlgorithms [0 ] = cpu_to_le16 (SIGNING_ALG_AES_CMAC );
452+
453+ ctxt_len += 2 /* sizeof le16 */ * num_algs ;
454+ ctxt_len = DIV_ROUND_UP (ctxt_len , 8 ) * 8 ;
455+ return ctxt_len ;
456+ /* TBD add SIGNING_ALG_AES_GMAC and/or SIGNING_ALG_HMAC_SHA256 */
457+ }
458+
436459static void
437460build_encrypt_ctxt (struct smb2_encryption_neg_context * pneg_ctxt )
438461{
@@ -498,7 +521,7 @@ assemble_neg_contexts(struct smb2_negotiate_req *req,
498521 struct TCP_Server_Info * server , unsigned int * total_len )
499522{
500523 char * pneg_ctxt ;
501- unsigned int ctxt_len ;
524+ unsigned int ctxt_len , neg_context_count ;
502525
503526 if (* total_len > 200 ) {
504527 /* In case length corrupted don't want to overrun smb buffer */
@@ -525,6 +548,17 @@ assemble_neg_contexts(struct smb2_negotiate_req *req,
525548 * total_len += ctxt_len ;
526549 pneg_ctxt += ctxt_len ;
527550
551+ ctxt_len = build_netname_ctxt ((struct smb2_netname_neg_context * )pneg_ctxt ,
552+ server -> hostname );
553+ * total_len += ctxt_len ;
554+ pneg_ctxt += ctxt_len ;
555+
556+ build_posix_ctxt ((struct smb2_posix_neg_context * )pneg_ctxt );
557+ * total_len += sizeof (struct smb2_posix_neg_context );
558+ pneg_ctxt += sizeof (struct smb2_posix_neg_context );
559+
560+ neg_context_count = 4 ;
561+
528562 if (server -> compress_algorithm ) {
529563 build_compression_ctxt ((struct smb2_compression_capabilities_context * )
530564 pneg_ctxt );
@@ -533,17 +567,20 @@ assemble_neg_contexts(struct smb2_negotiate_req *req,
533567 8 ) * 8 ;
534568 * total_len += ctxt_len ;
535569 pneg_ctxt += ctxt_len ;
536- req -> NegotiateContextCount = cpu_to_le16 (5 );
537- } else
538- req -> NegotiateContextCount = cpu_to_le16 (4 );
570+ neg_context_count ++ ;
571+ }
539572
540- ctxt_len = build_netname_ctxt ((struct smb2_netname_neg_context * )pneg_ctxt ,
541- server -> hostname );
542- * total_len += ctxt_len ;
543- pneg_ctxt += ctxt_len ;
573+ if (enable_negotiate_signing ) {
574+ ctxt_len = build_signing_ctxt ((struct smb2_signing_capabilities * )
575+ pneg_ctxt );
576+ * total_len += ctxt_len ;
577+ pneg_ctxt += ctxt_len ;
578+ neg_context_count ++ ;
579+ }
580+
581+ /* check for and add transport_capabilities and signing capabilities */
582+ req -> NegotiateContextCount = cpu_to_le16 (neg_context_count );
544583
545- build_posix_ctxt ((struct smb2_posix_neg_context * )pneg_ctxt );
546- * total_len += sizeof (struct smb2_posix_neg_context );
547584}
548585
549586static void decode_preauth_context (struct smb2_preauth_neg_context * ctxt )
@@ -632,6 +669,31 @@ static int decode_encrypt_ctx(struct TCP_Server_Info *server,
632669 return 0 ;
633670}
634671
672+ static void decode_signing_ctx (struct TCP_Server_Info * server ,
673+ struct smb2_signing_capabilities * pctxt )
674+ {
675+ unsigned int len = le16_to_cpu (pctxt -> DataLength );
676+
677+ if ((len < 4 ) || (len > 16 )) {
678+ pr_warn_once ("server sent bad signing negcontext\n" );
679+ return ;
680+ }
681+ if (le16_to_cpu (pctxt -> SigningAlgorithmCount ) != 1 ) {
682+ pr_warn_once ("Invalid signing algorithm count\n" );
683+ return ;
684+ }
685+ if (le16_to_cpu (pctxt -> SigningAlgorithms [0 ]) > 2 ) {
686+ pr_warn_once ("unknown signing algorithm\n" );
687+ return ;
688+ }
689+
690+ server -> signing_negotiated = true;
691+ server -> signing_algorithm = le16_to_cpu (pctxt -> SigningAlgorithms [0 ]);
692+ cifs_dbg (FYI , "signing algorithm %d chosen\n" ,
693+ server -> signing_algorithm );
694+ }
695+
696+
635697static int smb311_decode_neg_context (struct smb2_negotiate_rsp * rsp ,
636698 struct TCP_Server_Info * server ,
637699 unsigned int len_of_smb )
@@ -675,6 +737,9 @@ static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp,
675737 (struct smb2_compression_capabilities_context * )pctx );
676738 else if (pctx -> ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE )
677739 server -> posix_ext_supported = true;
740+ else if (pctx -> ContextType == SMB2_SIGNING_CAPABILITIES )
741+ decode_signing_ctx (server ,
742+ (struct smb2_signing_capabilities * )pctx );
678743 else
679744 cifs_server_dbg (VFS , "unknown negcontext of type %d ignored\n" ,
680745 le16_to_cpu (pctx -> ContextType ));
0 commit comments