2005-04-16 15:20:36 -07:00
/*
* linux / net / sunrpc / gss_krb5_unseal . c
*
* Adapted from MIT Kerberos 5 - 1.2 .1 lib / gssapi / krb5 / k5unseal . c
*
2010-03-17 13:02:51 -04:00
* Copyright ( c ) 2000 - 2008 The Regents of the University of Michigan .
2005-04-16 15:20:36 -07:00
* All rights reserved .
*
* Andy Adamson < andros @ umich . edu >
*/
/*
* Copyright 1993 by OpenVision Technologies , Inc .
*
* Permission to use , copy , modify , distribute , and sell this software
* and its documentation for any purpose is hereby granted without fee ,
* provided that the above copyright notice appears in all copies and
* that both that copyright notice and this permission notice appear in
* supporting documentation , and that the name of OpenVision not be used
* in advertising or publicity pertaining to distribution of the software
* without specific , written prior permission . OpenVision makes no
* representations about the suitability of this software for any
* purpose . It is provided " as is " without express or implied warranty .
*
* OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE ,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS , IN NO
* EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL , INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE , DATA OR PROFITS , WHETHER IN AN ACTION OF CONTRACT , NEGLIGENCE OR
* OTHER TORTIOUS ACTION , ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE .
*/
/*
* Copyright ( C ) 1998 by the FundsXpress , INC .
*
* All rights reserved .
*
* Export of this software from the United States of America may require
* a specific license from the United States Government . It is the
* responsibility of any person or organization contemplating export to
* obtain such a license before exporting .
*
* WITHIN THAT CONSTRAINT , permission to use , copy , modify , and
* distribute this software and its documentation for any purpose and
* without fee is hereby granted , provided that the above copyright
* notice appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation , and that
* the name of FundsXpress . not be used in advertising or publicity pertaining
* to distribution of the software without specific , written prior
* permission . FundsXpress makes no representations about the suitability of
* this software for any purpose . It is provided " as is " without express
* or implied warranty .
*
* THIS SOFTWARE IS PROVIDED ` ` AS IS ' ' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES , INCLUDING , WITHOUT LIMITATION , THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE .
*/
# include <linux/types.h>
# include <linux/jiffies.h>
# include <linux/sunrpc/gss_krb5.h>
# include <linux/crypto.h>
# ifdef RPC_DEBUG
# define RPCDBG_FACILITY RPCDBG_AUTH
# endif
2005-10-13 16:55:08 -04:00
/* read_token is a mic token, and message_buffer is the data that the mic was
* supposedly taken over . */
2005-04-16 15:20:36 -07:00
2010-03-17 13:02:49 -04:00
static u32
gss_verify_mic_v1 ( struct krb5_ctx * ctx ,
2005-10-13 16:55:23 -04:00
struct xdr_buf * message_buffer , struct xdr_netobj * read_token )
2005-04-16 15:20:36 -07:00
{
int signalg ;
int sealalg ;
2010-03-17 13:02:51 -04:00
char cksumdata [ GSS_KRB5_MAX_CKSUM_LEN ] ;
struct xdr_netobj md5cksum = { . len = sizeof ( cksumdata ) ,
. data = cksumdata } ;
2005-04-16 15:20:36 -07:00
s32 now ;
int direction ;
2008-03-31 10:31:33 -04:00
u32 seqnum ;
2005-04-16 15:20:36 -07:00
unsigned char * ptr = ( unsigned char * ) read_token - > data ;
int bodysize ;
2010-03-17 13:02:52 -04:00
u8 * cksumkey ;
2005-04-16 15:20:36 -07:00
2007-01-31 12:14:05 -05:00
dprintk ( " RPC: krb5_read_token \n " ) ;
2005-04-16 15:20:36 -07:00
if ( g_verify_token_header ( & ctx - > mech_used , & bodysize , & ptr ,
read_token - > len ) )
2006-12-04 20:22:39 -05:00
return GSS_S_DEFECTIVE_TOKEN ;
2005-04-16 15:20:36 -07:00
2008-04-30 12:45:53 -04:00
if ( ( ptr [ 0 ] ! = ( ( KG_TOK_MIC_MSG > > 8 ) & 0xff ) ) | |
( ptr [ 1 ] ! = ( KG_TOK_MIC_MSG & 0xff ) ) )
2006-12-04 20:22:39 -05:00
return GSS_S_DEFECTIVE_TOKEN ;
2005-04-16 15:20:36 -07:00
/* XXX sanity-check bodysize?? */
2008-04-30 12:45:53 -04:00
signalg = ptr [ 2 ] + ( ptr [ 3 ] < < 8 ) ;
2010-03-17 13:02:51 -04:00
if ( signalg ! = ctx - > gk5e - > signalg )
2006-12-04 20:22:39 -05:00
return GSS_S_DEFECTIVE_TOKEN ;
2005-04-16 15:20:36 -07:00
2008-04-30 12:45:53 -04:00
sealalg = ptr [ 4 ] + ( ptr [ 5 ] < < 8 ) ;
2006-12-04 20:22:42 -05:00
if ( sealalg ! = SEAL_ALG_NONE )
2006-12-04 20:22:39 -05:00
return GSS_S_DEFECTIVE_TOKEN ;
2006-12-04 20:22:42 -05:00
2008-04-30 12:45:53 -04:00
if ( ( ptr [ 6 ] ! = 0xff ) | | ( ptr [ 7 ] ! = 0xff ) )
2006-12-04 20:22:39 -05:00
return GSS_S_DEFECTIVE_TOKEN ;
2005-04-16 15:20:36 -07:00
2010-03-17 13:02:52 -04:00
if ( ctx - > gk5e - > keyed_cksum )
cksumkey = ctx - > cksum ;
else
cksumkey = NULL ;
2006-12-04 20:22:36 -05:00
2010-03-17 13:02:52 -04:00
if ( make_checksum ( ctx , ptr , 8 , message_buffer , 0 ,
2010-03-17 13:03:02 -04:00
cksumkey , KG_USAGE_SIGN , & md5cksum ) )
2006-12-04 20:22:39 -05:00
return GSS_S_FAILURE ;
2005-04-16 15:20:36 -07:00
2010-03-17 13:02:52 -04:00
if ( memcmp ( md5cksum . data , ptr + GSS_KRB5_TOK_HDR_LEN ,
2010-03-17 13:02:51 -04:00
ctx - > gk5e - > cksumlength ) )
2006-12-04 20:22:39 -05:00
return GSS_S_BAD_SIG ;
2005-04-16 15:20:36 -07:00
/* it got through unscathed. Make sure the context is unexpired */
now = get_seconds ( ) ;
if ( now > ctx - > endtime )
2006-12-04 20:22:39 -05:00
return GSS_S_CONTEXT_EXPIRED ;
2005-04-16 15:20:36 -07:00
/* do sequencing checks */
2010-03-17 13:03:04 -04:00
if ( krb5_get_seq_num ( ctx , ptr + GSS_KRB5_TOK_HDR_LEN , ptr + 8 ,
& direction , & seqnum ) )
2006-12-04 20:22:39 -05:00
return GSS_S_FAILURE ;
2005-04-16 15:20:36 -07:00
if ( ( ctx - > initiate & & direction ! = 0xff ) | |
( ! ctx - > initiate & & direction ! = 0 ) )
2006-12-04 20:22:39 -05:00
return GSS_S_BAD_SIG ;
2005-04-16 15:20:36 -07:00
2006-12-04 20:22:39 -05:00
return GSS_S_COMPLETE ;
2005-04-16 15:20:36 -07:00
}
2010-03-17 13:02:49 -04:00
2010-03-17 13:02:59 -04:00
static u32
gss_verify_mic_v2 ( struct krb5_ctx * ctx ,
struct xdr_buf * message_buffer , struct xdr_netobj * read_token )
{
char cksumdata [ GSS_KRB5_MAX_CKSUM_LEN ] ;
struct xdr_netobj cksumobj = { . len = sizeof ( cksumdata ) ,
. data = cksumdata } ;
s32 now ;
u64 seqnum ;
u8 * ptr = read_token - > data ;
u8 * cksumkey ;
u8 flags ;
int i ;
2010-03-17 13:03:02 -04:00
unsigned int cksum_usage ;
2010-03-17 13:02:59 -04:00
dprintk ( " RPC: %s \n " , __func__ ) ;
if ( be16_to_cpu ( * ( ( __be16 * ) ptr ) ) ! = KG2_TOK_MIC )
return GSS_S_DEFECTIVE_TOKEN ;
flags = ptr [ 2 ] ;
if ( ( ! ctx - > initiate & & ( flags & KG2_TOKEN_FLAG_SENTBYACCEPTOR ) ) | |
( ctx - > initiate & & ! ( flags & KG2_TOKEN_FLAG_SENTBYACCEPTOR ) ) )
return GSS_S_BAD_SIG ;
if ( flags & KG2_TOKEN_FLAG_SEALED ) {
dprintk ( " %s: token has unexpected sealed flag \n " , __func__ ) ;
return GSS_S_FAILURE ;
}
for ( i = 3 ; i < 8 ; i + + )
if ( ptr [ i ] ! = 0xff )
return GSS_S_DEFECTIVE_TOKEN ;
2010-03-17 13:03:02 -04:00
if ( ctx - > initiate ) {
2010-03-17 13:02:59 -04:00
cksumkey = ctx - > acceptor_sign ;
2010-03-17 13:03:02 -04:00
cksum_usage = KG_USAGE_ACCEPTOR_SIGN ;
} else {
2010-03-17 13:02:59 -04:00
cksumkey = ctx - > initiator_sign ;
2010-03-17 13:03:02 -04:00
cksum_usage = KG_USAGE_INITIATOR_SIGN ;
}
2010-03-17 13:02:59 -04:00
if ( make_checksum_v2 ( ctx , ptr , GSS_KRB5_TOK_HDR_LEN , message_buffer , 0 ,
2010-03-17 13:03:02 -04:00
cksumkey , cksum_usage , & cksumobj ) )
2010-03-17 13:02:59 -04:00
return GSS_S_FAILURE ;
if ( memcmp ( cksumobj . data , ptr + GSS_KRB5_TOK_HDR_LEN ,
ctx - > gk5e - > cksumlength ) )
return GSS_S_BAD_SIG ;
/* it got through unscathed. Make sure the context is unexpired */
now = get_seconds ( ) ;
if ( now > ctx - > endtime )
return GSS_S_CONTEXT_EXPIRED ;
/* do sequencing checks */
seqnum = be64_to_cpup ( ( __be64 * ) ptr + 8 ) ;
return GSS_S_COMPLETE ;
}
2010-03-17 13:02:49 -04:00
u32
gss_verify_mic_kerberos ( struct gss_ctx * gss_ctx ,
struct xdr_buf * message_buffer ,
struct xdr_netobj * read_token )
{
struct krb5_ctx * ctx = gss_ctx - > internal_ctx_id ;
switch ( ctx - > enctype ) {
default :
BUG ( ) ;
case ENCTYPE_DES_CBC_RAW :
2010-03-17 13:02:55 -04:00
case ENCTYPE_DES3_CBC_RAW :
2010-03-17 13:03:06 -04:00
case ENCTYPE_ARCFOUR_HMAC :
2010-03-17 13:02:49 -04:00
return gss_verify_mic_v1 ( ctx , message_buffer , read_token ) ;
2010-03-17 13:02:59 -04:00
case ENCTYPE_AES128_CTS_HMAC_SHA1_96 :
case ENCTYPE_AES256_CTS_HMAC_SHA1_96 :
return gss_verify_mic_v2 ( ctx , message_buffer , read_token ) ;
2010-03-17 13:02:49 -04:00
}
}