Print this page
NEX-16824 SMB client connection setup rework
NEX-17232 SMB client reconnect failures
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
and: (improve debug)


  15  *    This product includes software developed by Boris Popov.
  16  * 4. Neither the name of the author nor the names of any co-contributors
  17  *    may be used to endorse or promote products derived from this software
  18  *    without specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30  * SUCH DAMAGE.
  31  */
  32 
  33 /*
  34  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.

  35  */
  36 
  37 /*
  38  * Kerberos V Security Support Provider
  39  *
  40  * Based on code previously in ctx.c (from Boris Popov?)
  41  * but then mostly rewritten at Sun.
  42  */
  43 
  44 #include <errno.h>
  45 #include <stdio.h>
  46 #include <stddef.h>
  47 #include <stdlib.h>
  48 #include <unistd.h>
  49 #include <strings.h>
  50 #include <netdb.h>
  51 #include <libintl.h>
  52 #include <xti.h>
  53 #include <assert.h>
  54 


 251 {
 252         int err;
 253         struct smb_ctx *ctx = sp->smb_ctx;
 254         krb5ssp_state_t *ss = sp->sp_private;
 255         uchar_t         *tkt = NULL;
 256         ulong_t         tktlen;
 257         uchar_t         *gtok = NULL;           /* gssapi token */
 258         ulong_t         gtoklen;                /* gssapi token length */
 259         char            *prin = ctx->ct_srvname;
 260 
 261         if ((err = krb5ssp_get_tkt(ss, prin, &tkt, &tktlen)) != 0)
 262                 goto out;
 263         if ((err = krb5ssp_tkt2gtok(tkt, tktlen, &gtok, &gtoklen)) != 0)
 264                 goto out;
 265 
 266         if ((err = mb_init_sz(out_mb, gtoklen)) != 0)
 267                 goto out;
 268         if ((err = mb_put_mem(out_mb, gtok, gtoklen, MB_MSYSTEM)) != 0)
 269                 goto out;
 270 
 271         if (ctx->ct_vcflags & SMBV_WILL_SIGN)
 272                 ctx->ct_hflags2 |= SMB_FLAGS2_SECURITY_SIGNATURE;
 273 
 274 out:
 275         if (gtok)
 276                 free(gtok);
 277         if (tkt)
 278                 free(tkt);
 279 
 280         return (err);
 281 }
 282 
 283 /*
 284  * Unwrap a GSS-API encapsulated RFC 1964 reply message,
 285  * i.e. type KRB_AP_REP or KRB_ERROR.
 286  */
 287 int
 288 krb5ssp_get_reply(struct ssp_ctx *sp, struct mbdata *in_mb)
 289 {
 290         krb5ssp_state_t *ss = sp->sp_private;
 291         mbuf_t *m = in_mb->mb_top;
 292         int err = EBADRPC;
 293         int dlen, rc;


 366         if (reply != NULL)
 367                 krb5_free_ap_rep_enc_part(ss->ss_krb5ctx, reply);
 368         if (err)
 369                 DPRINT("ret %d", err);
 370 
 371         return (err);
 372 }
 373 
 374 /*
 375  * krb5ssp_final
 376  *
 377  * Called after successful authentication.
 378  * Setup the MAC key for signing.
 379  */
 380 int
 381 krb5ssp_final(struct ssp_ctx *sp)
 382 {
 383         struct smb_ctx *ctx = sp->smb_ctx;
 384         krb5ssp_state_t *ss = sp->sp_private;
 385         krb5_keyblock   *ssn_key = NULL;
 386         int err, len;
 387 
 388         /*
 389          * Save the session key, used for SMB signing
 390          * and possibly other consumers (RPC).
 391          */
 392         err = krb5_auth_con_getlocalsubkey(
 393             ss->ss_krb5ctx, ss->ss_auth, &ssn_key);
 394         if (err != 0) {
 395                 DPRINT("_getlocalsubkey, err=0x%x (%s)",
 396                     err, error_message(err));
 397                 if (err <= 0 || err > ESTALE)
 398                         err = EAUTH;
 399                 goto out;
 400         }
 401         memset(ctx->ct_ssn_key, 0, SMBIOC_HASH_SZ);
 402         if ((len = ssn_key->length) > SMBIOC_HASH_SZ)
 403                 len = SMBIOC_HASH_SZ;
 404         memcpy(ctx->ct_ssn_key, ssn_key->contents, len);
 405 
 406         /*
 407          * Set the MAC key on the first successful auth.
 408          */
 409         if ((ctx->ct_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) &&
 410             (ctx->ct_mackey == NULL)) {
 411                 ctx->ct_mackeylen = ssn_key->length;
 412                 ctx->ct_mackey = malloc(ctx->ct_mackeylen);
 413                 if (ctx->ct_mackey == NULL) {
 414                         ctx->ct_mackeylen = 0;
 415                         err = ENOMEM;
 416                         goto out;
 417                 }
 418                 memcpy(ctx->ct_mackey, ssn_key->contents,
 419                     ctx->ct_mackeylen);
 420                 /*
 421                  * Apparently, the server used seq. no. zero
 422                  * for our previous message, so next is two.
 423                  */
 424                 ctx->ct_mac_seqno = 2;


 425         }







 426         err = 0;
 427 
 428 out:
 429         if (ssn_key)
 430                 krb5_free_keyblock(ss->ss_krb5ctx, ssn_key);
 431 
 432         return (err);
 433 }
 434 
 435 /*
 436  * krb5ssp_next_token
 437  *
 438  * See ssp.c: ssp_ctx_next_token
 439  */
 440 int
 441 krb5ssp_next_token(struct ssp_ctx *sp, struct mbdata *in_mb,
 442         struct mbdata *out_mb)
 443 {
 444         int err;
 445 
 446         /*
 447          * Note: in_mb == NULL on the first call.
 448          */
 449         if (in_mb) {




  15  *    This product includes software developed by Boris Popov.
  16  * 4. Neither the name of the author nor the names of any co-contributors
  17  *    may be used to endorse or promote products derived from this software
  18  *    without specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30  * SUCH DAMAGE.
  31  */
  32 
  33 /*
  34  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  35  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  36  */
  37 
  38 /*
  39  * Kerberos V Security Support Provider
  40  *
  41  * Based on code previously in ctx.c (from Boris Popov?)
  42  * but then mostly rewritten at Sun.
  43  */
  44 
  45 #include <errno.h>
  46 #include <stdio.h>
  47 #include <stddef.h>
  48 #include <stdlib.h>
  49 #include <unistd.h>
  50 #include <strings.h>
  51 #include <netdb.h>
  52 #include <libintl.h>
  53 #include <xti.h>
  54 #include <assert.h>
  55 


 252 {
 253         int err;
 254         struct smb_ctx *ctx = sp->smb_ctx;
 255         krb5ssp_state_t *ss = sp->sp_private;
 256         uchar_t         *tkt = NULL;
 257         ulong_t         tktlen;
 258         uchar_t         *gtok = NULL;           /* gssapi token */
 259         ulong_t         gtoklen;                /* gssapi token length */
 260         char            *prin = ctx->ct_srvname;
 261 
 262         if ((err = krb5ssp_get_tkt(ss, prin, &tkt, &tktlen)) != 0)
 263                 goto out;
 264         if ((err = krb5ssp_tkt2gtok(tkt, tktlen, &gtok, &gtoklen)) != 0)
 265                 goto out;
 266 
 267         if ((err = mb_init_sz(out_mb, gtoklen)) != 0)
 268                 goto out;
 269         if ((err = mb_put_mem(out_mb, gtok, gtoklen, MB_MSYSTEM)) != 0)
 270                 goto out;
 271 



 272 out:
 273         if (gtok)
 274                 free(gtok);
 275         if (tkt)
 276                 free(tkt);
 277 
 278         return (err);
 279 }
 280 
 281 /*
 282  * Unwrap a GSS-API encapsulated RFC 1964 reply message,
 283  * i.e. type KRB_AP_REP or KRB_ERROR.
 284  */
 285 int
 286 krb5ssp_get_reply(struct ssp_ctx *sp, struct mbdata *in_mb)
 287 {
 288         krb5ssp_state_t *ss = sp->sp_private;
 289         mbuf_t *m = in_mb->mb_top;
 290         int err = EBADRPC;
 291         int dlen, rc;


 364         if (reply != NULL)
 365                 krb5_free_ap_rep_enc_part(ss->ss_krb5ctx, reply);
 366         if (err)
 367                 DPRINT("ret %d", err);
 368 
 369         return (err);
 370 }
 371 
 372 /*
 373  * krb5ssp_final
 374  *
 375  * Called after successful authentication.
 376  * Setup the MAC key for signing.
 377  */
 378 int
 379 krb5ssp_final(struct ssp_ctx *sp)
 380 {
 381         struct smb_ctx *ctx = sp->smb_ctx;
 382         krb5ssp_state_t *ss = sp->sp_private;
 383         krb5_keyblock   *ssn_key = NULL;
 384         int err;
 385 
 386         /*
 387          * Save the session key, used for SMB signing
 388          * and possibly other consumers (RPC).
 389          */
 390         err = krb5_auth_con_getlocalsubkey(
 391             ss->ss_krb5ctx, ss->ss_auth, &ssn_key);
 392         if (err != 0) {
 393                 DPRINT("_getlocalsubkey, err=0x%x (%s)",
 394                     err, error_message(err));
 395                 if (err <= 0 || err > ESTALE)
 396                         err = EAUTH;
 397                 goto out;
 398         }




 399 
 400         /* Sanity check the length */
 401         if (ssn_key->length > 1024) {
 402                 DPRINT("session key too long");
 403                 err = EAUTH;






 404                 goto out;
 405         }
 406 

 407         /*
 408          * Update/save the session key.

 409          */
 410         if (ctx->ct_ssnkey_buf != NULL) {
 411                 free(ctx->ct_ssnkey_buf);
 412                 ctx->ct_ssnkey_buf = NULL;
 413         }
 414         ctx->ct_ssnkey_buf = malloc(ssn_key->length);
 415         if (ctx->ct_ssnkey_buf == NULL) {
 416                 err = ENOMEM;
 417                 goto out;
 418         }
 419         ctx->ct_ssnkey_len = ssn_key->length;
 420         memcpy(ctx->ct_ssnkey_buf, ssn_key->contents, ctx->ct_ssnkey_len);
 421         err = 0;
 422 
 423 out:
 424         if (ssn_key != NULL)
 425                 krb5_free_keyblock(ss->ss_krb5ctx, ssn_key);
 426 
 427         return (err);
 428 }
 429 
 430 /*
 431  * krb5ssp_next_token
 432  *
 433  * See ssp.c: ssp_ctx_next_token
 434  */
 435 int
 436 krb5ssp_next_token(struct ssp_ctx *sp, struct mbdata *in_mb,
 437         struct mbdata *out_mb)
 438 {
 439         int err;
 440 
 441         /*
 442          * Note: in_mb == NULL on the first call.
 443          */
 444         if (in_mb) {