2001-10-12 08:49:42 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2001-10-12 08:49:42 +04:00
simple kerberos5 / SPNEGO routines
Copyright ( C ) Andrew Tridgell 2001
2003-08-01 19:21:20 +04:00
Copyright ( C ) Jim McDonough < jmcd @ us . ibm . com > 2002
2003-03-18 01:45:16 +03:00
Copyright ( C ) Luke Howard 2003
2001-10-12 08:49:42 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2001-10-12 08:49:42 +04:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2001-10-12 08:49:42 +04:00
*/
# include "includes.h"
/*
generate a negTokenInit packet given a GUID , a list of supported
2001-10-22 00:51:27 +04:00
OIDs ( the mechanisms ) and a principal name string
2001-10-12 08:49:42 +04:00
*/
2005-10-18 07:24:00 +04:00
DATA_BLOB spnego_gen_negTokenInit ( char guid [ 16 ] ,
2001-10-12 08:49:42 +04:00
const char * OIDs [ ] ,
2001-10-22 00:51:27 +04:00
const char * principal )
2001-10-12 08:49:42 +04:00
{
int i ;
ASN1_DATA data ;
2001-10-17 12:54:19 +04:00
DATA_BLOB ret ;
2001-10-12 08:49:42 +04:00
memset ( & data , 0 , sizeof ( data ) ) ;
asn1_write ( & data , guid , 16 ) ;
asn1_push_tag ( & data , ASN1_APPLICATION ( 0 ) ) ;
asn1_write_OID ( & data , OID_SPNEGO ) ;
asn1_push_tag ( & data , ASN1_CONTEXT ( 0 ) ) ;
asn1_push_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_push_tag ( & data , ASN1_CONTEXT ( 0 ) ) ;
asn1_push_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
for ( i = 0 ; OIDs [ i ] ; i + + ) {
asn1_write_OID ( & data , OIDs [ i ] ) ;
}
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
asn1_push_tag ( & data , ASN1_CONTEXT ( 3 ) ) ;
asn1_push_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_push_tag ( & data , ASN1_CONTEXT ( 0 ) ) ;
2001-10-22 00:51:27 +04:00
asn1_write_GeneralString ( & data , principal ) ;
2001-10-12 08:49:42 +04:00
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
if ( data . has_error ) {
DEBUG ( 1 , ( " Failed to build negTokenInit at offset %d \n " , ( int ) data . ofs ) ) ;
asn1_free ( & data ) ;
}
2001-10-17 12:54:19 +04:00
ret = data_blob ( data . data , data . length ) ;
asn1_free ( & data ) ;
return ret ;
2001-10-12 08:49:42 +04:00
}
2002-09-25 19:19:00 +04:00
/*
Generate a negTokenInit as used by the client side . . . It has a mechType
( OID ) , and a mechToken ( a security blob ) . . .
Really , we need to break out the NTLMSSP stuff as well , because it could be
raw in the packets !
*/
DATA_BLOB gen_negTokenInit ( const char * OID , DATA_BLOB blob )
{
ASN1_DATA data ;
DATA_BLOB ret ;
memset ( & data , 0 , sizeof ( data ) ) ;
asn1_push_tag ( & data , ASN1_APPLICATION ( 0 ) ) ;
asn1_write_OID ( & data , OID_SPNEGO ) ;
asn1_push_tag ( & data , ASN1_CONTEXT ( 0 ) ) ;
asn1_push_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_push_tag ( & data , ASN1_CONTEXT ( 0 ) ) ;
asn1_push_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_write_OID ( & data , OID ) ;
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
asn1_push_tag ( & data , ASN1_CONTEXT ( 2 ) ) ;
asn1_write_OctetString ( & data , blob . data , blob . length ) ;
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
if ( data . has_error ) {
DEBUG ( 1 , ( " Failed to build negTokenInit at offset %d \n " , ( int ) data . ofs ) ) ;
asn1_free ( & data ) ;
}
ret = data_blob ( data . data , data . length ) ;
asn1_free ( & data ) ;
return ret ;
}
2001-10-12 08:49:42 +04:00
/*
parse a negTokenInit packet giving a GUID , a list of supported
2001-10-22 00:51:27 +04:00
OIDs ( the mechanisms ) and a principal name string
2001-10-12 08:49:42 +04:00
*/
BOOL spnego_parse_negTokenInit ( DATA_BLOB blob ,
char * OIDs [ ASN1_MAX_OIDS ] ,
2001-10-22 00:51:27 +04:00
char * * principal )
2001-10-12 08:49:42 +04:00
{
int i ;
BOOL ret ;
ASN1_DATA data ;
asn1_load ( & data , blob ) ;
asn1_start_tag ( & data , ASN1_APPLICATION ( 0 ) ) ;
asn1_check_OID ( & data , OID_SPNEGO ) ;
asn1_start_tag ( & data , ASN1_CONTEXT ( 0 ) ) ;
asn1_start_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_start_tag ( & data , ASN1_CONTEXT ( 0 ) ) ;
asn1_start_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
2006-06-12 22:32:25 +04:00
for ( i = 0 ; asn1_tag_remaining ( & data ) > 0 & & i < ASN1_MAX_OIDS - 1 ; i + + ) {
2004-06-24 23:25:20 +04:00
char * oid_str = NULL ;
asn1_read_OID ( & data , & oid_str ) ;
OIDs [ i ] = oid_str ;
2001-10-12 08:49:42 +04:00
}
OIDs [ i ] = NULL ;
asn1_end_tag ( & data ) ;
asn1_end_tag ( & data ) ;
2006-10-02 16:54:49 +04:00
* principal = NULL ;
if ( asn1_tag_remaining ( & data ) > 0 ) {
asn1_start_tag ( & data , ASN1_CONTEXT ( 3 ) ) ;
asn1_start_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_start_tag ( & data , ASN1_CONTEXT ( 0 ) ) ;
asn1_read_GeneralString ( & data , principal ) ;
asn1_end_tag ( & data ) ;
asn1_end_tag ( & data ) ;
asn1_end_tag ( & data ) ;
}
2001-10-12 08:49:42 +04:00
asn1_end_tag ( & data ) ;
asn1_end_tag ( & data ) ;
asn1_end_tag ( & data ) ;
ret = ! data . has_error ;
2006-06-17 02:25:17 +04:00
if ( data . has_error ) {
int j ;
2006-10-02 15:03:53 +04:00
SAFE_FREE ( * principal ) ;
2006-06-17 02:25:17 +04:00
for ( j = 0 ; j < i & & j < ASN1_MAX_OIDS - 1 ; j + + ) {
SAFE_FREE ( OIDs [ j ] ) ;
}
}
2001-10-12 08:49:42 +04:00
asn1_free ( & data ) ;
return ret ;
}
/*
generate a negTokenTarg packet given a list of OIDs and a security blob
*/
DATA_BLOB gen_negTokenTarg ( const char * OIDs [ ] , DATA_BLOB blob )
{
int i ;
ASN1_DATA data ;
DATA_BLOB ret ;
memset ( & data , 0 , sizeof ( data ) ) ;
asn1_push_tag ( & data , ASN1_APPLICATION ( 0 ) ) ;
asn1_write_OID ( & data , OID_SPNEGO ) ;
asn1_push_tag ( & data , ASN1_CONTEXT ( 0 ) ) ;
asn1_push_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_push_tag ( & data , ASN1_CONTEXT ( 0 ) ) ;
asn1_push_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
for ( i = 0 ; OIDs [ i ] ; i + + ) {
asn1_write_OID ( & data , OIDs [ i ] ) ;
}
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
asn1_push_tag ( & data , ASN1_CONTEXT ( 2 ) ) ;
asn1_write_OctetString ( & data , blob . data , blob . length ) ;
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
if ( data . has_error ) {
DEBUG ( 1 , ( " Failed to build negTokenTarg at offset %d \n " , ( int ) data . ofs ) ) ;
asn1_free ( & data ) ;
}
ret = data_blob ( data . data , data . length ) ;
asn1_free ( & data ) ;
return ret ;
}
2001-10-17 12:54:19 +04:00
/*
parse a negTokenTarg packet giving a list of OIDs and a security blob
*/
BOOL parse_negTokenTarg ( DATA_BLOB blob , char * OIDs [ ASN1_MAX_OIDS ] , DATA_BLOB * secblob )
{
int i ;
ASN1_DATA data ;
asn1_load ( & data , blob ) ;
asn1_start_tag ( & data , ASN1_APPLICATION ( 0 ) ) ;
asn1_check_OID ( & data , OID_SPNEGO ) ;
asn1_start_tag ( & data , ASN1_CONTEXT ( 0 ) ) ;
asn1_start_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_start_tag ( & data , ASN1_CONTEXT ( 0 ) ) ;
asn1_start_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
2006-06-12 22:32:25 +04:00
for ( i = 0 ; asn1_tag_remaining ( & data ) > 0 & & i < ASN1_MAX_OIDS - 1 ; i + + ) {
2004-06-24 23:25:20 +04:00
char * oid_str = NULL ;
asn1_read_OID ( & data , & oid_str ) ;
OIDs [ i ] = oid_str ;
2001-10-17 12:54:19 +04:00
}
OIDs [ i ] = NULL ;
asn1_end_tag ( & data ) ;
asn1_end_tag ( & data ) ;
asn1_start_tag ( & data , ASN1_CONTEXT ( 2 ) ) ;
asn1_read_OctetString ( & data , secblob ) ;
asn1_end_tag ( & data ) ;
asn1_end_tag ( & data ) ;
asn1_end_tag ( & data ) ;
asn1_end_tag ( & data ) ;
if ( data . has_error ) {
2006-06-17 02:25:17 +04:00
int j ;
data_blob_free ( secblob ) ;
for ( j = 0 ; j < i & & j < ASN1_MAX_OIDS - 1 ; j + + ) {
SAFE_FREE ( OIDs [ j ] ) ;
}
2001-10-17 12:54:19 +04:00
DEBUG ( 1 , ( " Failed to parse negTokenTarg at offset %d \n " , ( int ) data . ofs ) ) ;
asn1_free ( & data ) ;
return False ;
}
asn1_free ( & data ) ;
return True ;
}
2001-10-12 08:49:42 +04:00
/*
generate a krb5 GSS - API wrapper packet given a ticket
*/
2005-12-25 13:27:45 +03:00
DATA_BLOB spnego_gen_krb5_wrap ( const DATA_BLOB ticket , const uint8 tok_id [ 2 ] )
2001-10-12 08:49:42 +04:00
{
ASN1_DATA data ;
DATA_BLOB ret ;
memset ( & data , 0 , sizeof ( data ) ) ;
asn1_push_tag ( & data , ASN1_APPLICATION ( 0 ) ) ;
asn1_write_OID ( & data , OID_KERBEROS5 ) ;
2003-03-18 01:45:16 +03:00
asn1_write ( & data , tok_id , 2 ) ;
2001-10-12 08:49:42 +04:00
asn1_write ( & data , ticket . data , ticket . length ) ;
asn1_pop_tag ( & data ) ;
if ( data . has_error ) {
DEBUG ( 1 , ( " Failed to build krb5 wrapper at offset %d \n " , ( int ) data . ofs ) ) ;
asn1_free ( & data ) ;
}
ret = data_blob ( data . data , data . length ) ;
asn1_free ( & data ) ;
return ret ;
}
2001-10-18 14:26:06 +04:00
/*
parse a krb5 GSS - API wrapper packet giving a ticket
*/
2003-03-18 01:45:16 +03:00
BOOL spnego_parse_krb5_wrap ( DATA_BLOB blob , DATA_BLOB * ticket , uint8 tok_id [ 2 ] )
2001-10-18 14:26:06 +04:00
{
BOOL ret ;
ASN1_DATA data ;
2002-02-16 02:11:13 +03:00
int data_remaining ;
2001-10-18 14:26:06 +04:00
asn1_load ( & data , blob ) ;
asn1_start_tag ( & data , ASN1_APPLICATION ( 0 ) ) ;
asn1_check_OID ( & data , OID_KERBEROS5 ) ;
2002-02-16 02:11:13 +03:00
data_remaining = asn1_tag_remaining ( & data ) ;
2003-03-18 01:45:16 +03:00
if ( data_remaining < 3 ) {
2002-02-16 02:11:13 +03:00
data . has_error = True ;
} else {
2003-03-18 01:45:16 +03:00
asn1_read ( & data , tok_id , 2 ) ;
data_remaining - = 2 ;
* ticket = data_blob ( NULL , data_remaining ) ;
2002-02-16 02:11:13 +03:00
asn1_read ( & data , ticket - > data , ticket - > length ) ;
}
2001-10-18 14:26:06 +04:00
asn1_end_tag ( & data ) ;
ret = ! data . has_error ;
2006-06-17 02:25:17 +04:00
if ( data . has_error ) {
data_blob_free ( ticket ) ;
}
2001-10-18 14:26:06 +04:00
asn1_free ( & data ) ;
return ret ;
}
2001-10-12 08:49:42 +04:00
/*
generate a SPNEGO negTokenTarg packet , ready for a EXTENDED_SECURITY
kerberos session setup
*/
2004-01-08 11:19:18 +03:00
int spnego_gen_negTokenTarg ( const char * principal , int time_offset ,
DATA_BLOB * targ ,
2007-02-08 20:02:39 +03:00
DATA_BLOB * session_key_krb5 , uint32 extra_ap_opts ,
time_t * expire_time )
2001-10-12 08:49:42 +04:00
{
2004-01-08 11:19:18 +03:00
int retval ;
DATA_BLOB tkt , tkt_wrapped ;
2007-04-05 16:36:10 +04:00
const char * krb_mechs [ ] = { OID_KERBEROS5_OLD , OID_KERBEROS5 , OID_NTLMSSP , NULL } ;
2001-10-12 08:49:42 +04:00
2003-07-26 03:15:30 +04:00
/* get a kerberos ticket for the service and extract the session key */
2005-09-30 21:13:37 +04:00
retval = cli_krb5_get_ticket ( principal , time_offset ,
2007-02-08 20:02:39 +03:00
& tkt , session_key_krb5 , extra_ap_opts , NULL ,
expire_time ) ;
2001-10-12 08:49:42 +04:00
2004-01-08 11:19:18 +03:00
if ( retval )
return retval ;
2003-08-14 00:27:18 +04:00
2001-10-12 08:49:42 +04:00
/* wrap that up in a nice GSS-API wrapping */
2005-05-31 17:46:45 +04:00
tkt_wrapped = spnego_gen_krb5_wrap ( tkt , TOK_ID_KRB_AP_REQ ) ;
2001-10-12 08:49:42 +04:00
/* and wrap that in a shiny SPNEGO wrapper */
2004-01-08 11:19:18 +03:00
* targ = gen_negTokenTarg ( krb_mechs , tkt_wrapped ) ;
2001-10-12 08:49:42 +04:00
2001-10-17 12:54:19 +04:00
data_blob_free ( & tkt_wrapped ) ;
data_blob_free ( & tkt ) ;
2001-10-12 08:49:42 +04:00
2004-01-08 11:19:18 +03:00
return retval ;
2001-10-12 08:49:42 +04:00
}
/*
parse a spnego NTLMSSP challenge packet giving two security blobs
*/
2003-02-19 15:31:16 +03:00
BOOL spnego_parse_challenge ( const DATA_BLOB blob ,
2001-10-12 08:49:42 +04:00
DATA_BLOB * chal1 , DATA_BLOB * chal2 )
{
BOOL ret ;
ASN1_DATA data ;
2001-10-14 10:14:11 +04:00
ZERO_STRUCTP ( chal1 ) ;
ZERO_STRUCTP ( chal2 ) ;
2001-10-12 08:49:42 +04:00
asn1_load ( & data , blob ) ;
asn1_start_tag ( & data , ASN1_CONTEXT ( 1 ) ) ;
asn1_start_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_start_tag ( & data , ASN1_CONTEXT ( 0 ) ) ;
asn1_check_enumerated ( & data , 1 ) ;
asn1_end_tag ( & data ) ;
asn1_start_tag ( & data , ASN1_CONTEXT ( 1 ) ) ;
2001-10-12 08:54:53 +04:00
asn1_check_OID ( & data , OID_NTLMSSP ) ;
2001-10-12 08:49:42 +04:00
asn1_end_tag ( & data ) ;
asn1_start_tag ( & data , ASN1_CONTEXT ( 2 ) ) ;
2001-10-17 12:54:19 +04:00
asn1_read_OctetString ( & data , chal1 ) ;
2001-10-12 08:49:42 +04:00
asn1_end_tag ( & data ) ;
2001-10-14 10:14:11 +04:00
/* the second challenge is optional (XP doesn't send it) */
if ( asn1_tag_remaining ( & data ) ) {
asn1_start_tag ( & data , ASN1_CONTEXT ( 3 ) ) ;
2001-10-17 12:54:19 +04:00
asn1_read_OctetString ( & data , chal2 ) ;
2001-10-14 10:14:11 +04:00
asn1_end_tag ( & data ) ;
}
2001-10-12 08:49:42 +04:00
asn1_end_tag ( & data ) ;
asn1_end_tag ( & data ) ;
ret = ! data . has_error ;
2006-06-17 02:25:17 +04:00
if ( data . has_error ) {
data_blob_free ( chal1 ) ;
data_blob_free ( chal2 ) ;
}
2001-10-12 08:49:42 +04:00
asn1_free ( & data ) ;
return ret ;
}
2001-10-17 12:54:19 +04:00
2001-10-12 08:49:42 +04:00
/*
2003-02-19 15:31:16 +03:00
generate a SPNEGO auth packet . This will contain the encrypted passwords
2001-10-12 08:49:42 +04:00
*/
DATA_BLOB spnego_gen_auth ( DATA_BLOB blob )
{
ASN1_DATA data ;
DATA_BLOB ret ;
memset ( & data , 0 , sizeof ( data ) ) ;
asn1_push_tag ( & data , ASN1_CONTEXT ( 1 ) ) ;
asn1_push_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_push_tag ( & data , ASN1_CONTEXT ( 2 ) ) ;
asn1_write_OctetString ( & data , blob . data , blob . length ) ;
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
ret = data_blob ( data . data , data . length ) ;
asn1_free ( & data ) ;
return ret ;
2001-10-17 12:54:19 +04:00
}
/*
2003-02-19 15:31:16 +03:00
parse a SPNEGO auth packet . This contains the encrypted passwords
2001-10-17 12:54:19 +04:00
*/
BOOL spnego_parse_auth ( DATA_BLOB blob , DATA_BLOB * auth )
{
ASN1_DATA data ;
asn1_load ( & data , blob ) ;
asn1_start_tag ( & data , ASN1_CONTEXT ( 1 ) ) ;
asn1_start_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_start_tag ( & data , ASN1_CONTEXT ( 2 ) ) ;
asn1_read_OctetString ( & data , auth ) ;
asn1_end_tag ( & data ) ;
asn1_end_tag ( & data ) ;
asn1_end_tag ( & data ) ;
if ( data . has_error ) {
DEBUG ( 3 , ( " spnego_parse_auth failed at %d \n " , ( int ) data . ofs ) ) ;
2006-06-17 02:25:17 +04:00
data_blob_free ( auth ) ;
2001-10-17 12:54:19 +04:00
asn1_free ( & data ) ;
return False ;
}
asn1_free ( & data ) ;
return True ;
2001-10-12 08:49:42 +04:00
}
2002-08-17 21:00:51 +04:00
/*
2003-03-18 01:45:16 +03:00
generate a minimal SPNEGO response packet . Doesn ' t contain much .
2002-08-17 21:00:51 +04:00
*/
2003-03-18 01:45:16 +03:00
DATA_BLOB spnego_gen_auth_response ( DATA_BLOB * reply , NTSTATUS nt_status ,
const char * mechOID )
2002-08-17 21:00:51 +04:00
{
ASN1_DATA data ;
DATA_BLOB ret ;
2003-01-28 15:07:02 +03:00
uint8 negResult ;
2002-08-17 21:00:51 +04:00
2003-01-28 15:07:02 +03:00
if ( NT_STATUS_IS_OK ( nt_status ) ) {
2003-02-19 15:31:16 +03:00
negResult = SPNEGO_NEG_RESULT_ACCEPT ;
2003-01-28 15:07:02 +03:00
} else if ( NT_STATUS_EQUAL ( nt_status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) {
2003-02-19 15:31:16 +03:00
negResult = SPNEGO_NEG_RESULT_INCOMPLETE ;
2003-01-28 15:07:02 +03:00
} else {
2003-02-19 15:31:16 +03:00
negResult = SPNEGO_NEG_RESULT_REJECT ;
2003-01-28 15:07:02 +03:00
}
ZERO_STRUCT ( data ) ;
2002-08-17 21:00:51 +04:00
asn1_push_tag ( & data , ASN1_CONTEXT ( 1 ) ) ;
asn1_push_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_push_tag ( & data , ASN1_CONTEXT ( 0 ) ) ;
2003-01-28 15:07:02 +03:00
asn1_write_enumerated ( & data , negResult ) ;
2002-08-17 21:00:51 +04:00
asn1_pop_tag ( & data ) ;
2003-02-19 15:31:16 +03:00
2003-03-18 01:45:16 +03:00
if ( reply - > data ! = NULL ) {
2003-01-28 15:07:02 +03:00
asn1_push_tag ( & data , ASN1_CONTEXT ( 1 ) ) ;
2003-03-18 01:45:16 +03:00
asn1_write_OID ( & data , mechOID ) ;
2003-01-28 15:07:02 +03:00
asn1_pop_tag ( & data ) ;
asn1_push_tag ( & data , ASN1_CONTEXT ( 2 ) ) ;
2003-03-18 01:45:16 +03:00
asn1_write_OctetString ( & data , reply - > data , reply - > length ) ;
2003-01-28 15:07:02 +03:00
asn1_pop_tag ( & data ) ;
}
2002-08-17 21:00:51 +04:00
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
ret = data_blob ( data . data , data . length ) ;
asn1_free ( & data ) ;
return ret ;
}
2001-10-12 08:49:42 +04:00
/*
2007-04-05 16:30:23 +04:00
parse a SPNEGO auth packet . This contains the encrypted passwords
2003-02-24 05:55:00 +03:00
*/
2007-04-05 16:30:23 +04:00
BOOL spnego_parse_auth_response ( DATA_BLOB blob , NTSTATUS nt_status ,
const char * mechOID ,
2003-02-24 05:55:00 +03:00
DATA_BLOB * auth )
2001-10-12 08:49:42 +04:00
{
2003-02-24 05:55:00 +03:00
ASN1_DATA data ;
uint8 negResult ;
2001-10-12 08:49:42 +04:00
2003-02-24 05:55:00 +03:00
if ( NT_STATUS_IS_OK ( nt_status ) ) {
negResult = SPNEGO_NEG_RESULT_ACCEPT ;
} else if ( NT_STATUS_EQUAL ( nt_status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) {
negResult = SPNEGO_NEG_RESULT_INCOMPLETE ;
} else {
negResult = SPNEGO_NEG_RESULT_REJECT ;
}
2001-10-17 12:54:19 +04:00
2003-02-24 05:55:00 +03:00
asn1_load ( & data , blob ) ;
asn1_start_tag ( & data , ASN1_CONTEXT ( 1 ) ) ;
asn1_start_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_start_tag ( & data , ASN1_CONTEXT ( 0 ) ) ;
asn1_check_enumerated ( & data , negResult ) ;
asn1_end_tag ( & data ) ;
2001-10-17 12:54:19 +04:00
2007-05-14 16:16:20 +04:00
* auth = data_blob_null ;
2007-04-05 16:30:23 +04:00
if ( asn1_tag_remaining ( & data ) ) {
2003-02-24 05:55:00 +03:00
asn1_start_tag ( & data , ASN1_CONTEXT ( 1 ) ) ;
2007-04-05 16:30:23 +04:00
asn1_check_OID ( & data , mechOID ) ;
2003-02-24 05:55:00 +03:00
asn1_end_tag ( & data ) ;
2007-04-05 16:30:23 +04:00
if ( asn1_tag_remaining ( & data ) ) {
asn1_start_tag ( & data , ASN1_CONTEXT ( 2 ) ) ;
asn1_read_OctetString ( & data , auth ) ;
asn1_end_tag ( & data ) ;
}
} else if ( negResult = = SPNEGO_NEG_RESULT_INCOMPLETE ) {
data . has_error = 1 ;
2001-10-17 12:54:19 +04:00
}
2003-02-24 05:55:00 +03:00
asn1_end_tag ( & data ) ;
asn1_end_tag ( & data ) ;
2002-07-15 14:35:28 +04:00
2003-02-24 05:55:00 +03:00
if ( data . has_error ) {
DEBUG ( 3 , ( " spnego_parse_auth_response failed at %d \n " , ( int ) data . ofs ) ) ;
asn1_free ( & data ) ;
data_blob_free ( auth ) ;
return False ;
}
2002-07-15 14:35:28 +04:00
2003-02-24 05:55:00 +03:00
asn1_free ( & data ) ;
return True ;
2002-07-15 14:35:28 +04:00
}