VOMS-Lite

 view release on metacpan or  search on metacpan

lib/VOMS/Lite/VOMS.pm  view on Meta::CPAN

    push @ReqASN1DN,substr($ReqDistinguishedNames,0,$DNLen,'');
  }

# Get ServerHelloDone
  my $sHelloDone=$Hand{14};

# Check for RSA
  if ($RSAOK==0) { return { Errors => ErrWarn("Server does not support RSA AuthN"), Warnings => \@warning }; } 

# 1, Check acceptable DNs for Certificates
  my $GotCA=0;
  foreach (@ReqASN1DN) {
    my $X509subject=$_;
    my @ASN1SubjectDNIndex=ASN1Index($X509subject);
    shift @ASN1SubjectDNIndex;
    my $SubjectDN="";
    while (@ASN1SubjectDNIndex) {
      my ($CLASS,$CONSTRUCTED,$TAG,$HEADSTART,$HEADLEN,$CHUNKLEN)=(0,0,0,0,0);
      until ($TAG == 6 ) { ($CLASS,$CONSTRUCTED,$TAG,$HEADSTART,$HEADLEN,$CHUNKLEN) = @{shift @ASN1SubjectDNIndex}; }
      my $OID=substr($X509subject,($HEADSTART+$HEADLEN),$CHUNKLEN);
      ($CLASS,$CONSTRUCTED,$TAG,$HEADSTART,$HEADLEN,$CHUNKLEN) = @{shift @ASN1SubjectDNIndex};
      my $Value=substr($X509subject,($HEADSTART+$HEADLEN),$CHUNKLEN);
      $SubjectDN.="/".VOMS::Lite::CertKeyHelper::OIDtoDNattrib(ASN1OIDtoOID($OID))."=$Value";
    }
    if ($UserIDN eq $SubjectDN) { debug("MATCHED CA",$SubjectDN); $GotCA=1; } 
    else                        { debug("        CA:", $SubjectDN); }
  }
  if ( @ReqASN1DN == 0 ) { ErrWarn(\@warning, "VOMS server does not tell me what CAs are supported"); }
  elsif ( $GotCA==0 )    { return { Errors => ErrWarn("VOMS server does not support your CA"), Warnings => \@warning }; }

#########################################################
#Talk to the server again

##Construct Certificate Message Record
  my $hexcertarray =""; 
  foreach my $cert (@chain) { $hexcertarray.=sprintf("%06s",DecToHex(length($cert))).Hex($cert);}
  my $hexcertobj      = sprintf("%06s",DecToHex(length($hexcertarray)/2)).$hexcertarray;
  my $hexcertmesg     = handShake("0b",$hexcertobj);
  my $hexcertsmessagerecord=recordLayer("16",$hexcertmesg);
  my $certmesg = pack("H*", $hexcertmesg); 

##ClientKeyExchange
#PreMasterSecret
  my $prernd='X' x 46;  $prernd =~ s/./chr(int(rand 256))/ge;
  my $hexpremastersecret='0300'.Hex($prernd);

#Derive Key Material
  my %KEYS=Keygen($hexpremastersecret,$hexrandom,Hex($sHelloTime.$sHelloRand));

#Make Client Key Exchange
  my $hexEncPMSecret   = rsaencrypt($hexpremastersecret,Hex($ServerCertInfo{'KeypublicExponent'}),Hex($ServerCertInfo{'Keymodulus'}));
  my $hexClientKeyExchange  = handShake("10",$hexEncPMSecret);    #### USE ME FOR CertificateVarify
  my $hexClientKeyExchangeMessageRecord = recordLayer("16",$hexClientKeyExchange);
  my $ClientKeyExchangeMessage = Bin($hexClientKeyExchange); #### ClientCertificate for handshakemessages needs to be without record layer

#CertificateVerify
  my $Hmsgs     = $clienthello.$serverhello.$certmesg.$ClientKeyExchangeMessage;
  my $verifymac = MAC($KEYS{'MS'},$Hmsgs);

  my $hexsignedcertificateverify        = rsasign($verifymac,$Keyexp,$Keymod);
  my $hexwrappedsignedcertificateverify = sprintf("%04s",DecToHex(length($hexsignedcertificateverify)/2)).$hexsignedcertificateverify;
  my $hexcertificateverify              = handShake('0f',$hexwrappedsignedcertificateverify);
  my $certificateverify                 = Bin($hexcertificateverify);
  my $hex_ssl_certificateverifyrecord   = recordLayer("16",$hexcertificateverify);

##########################################################################
## Switch to Encrypted Session -- change_cipher_spec message
#Select algorythm for key exchange -- Must be RSA
  my $hexkeyselection="140300000101";

# Switch to tripple des (the only one I support) and send finished message

  $Hmsgs.=$certificateverify;
  my $unechexfinished=handShake("14",MAC($KEYS{'MS'},$Hmsgs."CLNT"));

#Set up the Client and Server DES3-EDE sessions
  my $Ccipher = Crypt::CBC->new( -literal_key => 1, -padding => 'null', -key => $KEYS{'CK'},  -iv => $KEYS{'CIV'}, -header => 'none', -cipher => 'DES_EDE3' );
  my $Scipher = Crypt::CBC->new( -literal_key => 1, -padding => 'null', -key => $KEYS{'SK'},  -iv => $KEYS{'SIV'}, -header => 'none', -cipher => 'DES_EDE3' );
  my $Cseq=0;
  my $Sseq=0;

  my $hex_finishedrecord = &Encrypt(Bin(recordLayer("16",$unechexfinished)),$KEYS{'CMAC'},$pad1sha,$pad2sha,$Cseq,$Ccipher);
  my $hex_finished       = $hex_finishedrecord;
  $hex_finished         =~ s/^..........//s;
  my $finished           = Bin($hex_finished);

#############################################################################
#Send Records
  Write($sock,Bin($hexcertsmessagerecord.$hexClientKeyExchangeMessageRecord.$hex_ssl_certificateverifyrecord.$hexkeyselection.$hex_finishedrecord));

#############################################################################
#Receive Response
  $response=Read($sock);
  if ( $response =~ /^\x14\x03\x00\x00\x01\x01/ ) {  $response =~ s/......//; } #Change Cypher Spec -- what we expect
  else { return { Errors => ErrWarn("Error: Expecting SSL Change Cypher Spec Message, got something else."), Warnings => \@warning }; }
  my $serverfinishedhex=Hex(&Decrypt($response,$KEYS{'SMAC'},$pad1sha,$pad2sha,$Sseq,$Scipher));

# Check response from server is a valid finished message
  $Hmsgs.=Bin($unechexfinished);
  my $unencryptedfinishedmsg = handShake("14",MAC($KEYS{'MS'},$Hmsgs."SRVR"));
  if ($unencryptedfinishedmsg ne $serverfinishedhex) { return { Errors => ErrWarn("Failed to decrypt Server Finished Message"), Warnings => \@warning }; }

######################### 
# Send no delegation byte
# predata and postdata to stop TLS CBC IV attack
  my $predata      = Bin(&Encrypt(Bin("1703000000"),$KEYS{'CMAC'},$pad1sha,$pad2sha,$Cseq,$Ccipher));
  my $msg='0';
  my $emesg        = &Encrypt(Bin(recordLayer("17",Hex($msg))),$KEYS{'CMAC'},$pad1sha,$pad2sha,$Cseq,$Ccipher);
  $senddata        = Bin($emesg);
  my $postdata     = Bin(&Encrypt(Bin("1703000000"),$KEYS{'CMAC'},$pad1sha,$pad2sha,$Cseq,$Ccipher));

  Write($sock,$predata.$senddata.$postdata);

############## 
# Send request
#<xml version="1.0" encoding = "US-ASCII"?>
#  <voms>
#    <command>COMMAND</command>+
#    <order>ORDER</order>?
#    <targets>TARGETS</targets>?
#    <lifetime>N</lifetime>?
#    <base64>B</base64>?

lib/VOMS/Lite/VOMS.pm  view on Meta::CPAN

    push @ReqASN1DN,substr($ReqDistinguishedNames,0,$DNLen,'');
  }

# Get ServerHelloDone
  my $sHelloDone=$Hand{14};

# Check for RSA
  if ($RSAOK==0) { return { Errors => ErrWarn("Server does not support RSA AuthN"), Warnings => \@warning }; } 

# 1, Check acceptable DNs for Certificates
  my $GotCA=0;
  foreach (@ReqASN1DN) {
    my $X509subject=$_;
    my @ASN1SubjectDNIndex=ASN1Index($X509subject);
    shift @ASN1SubjectDNIndex;
    my $SubjectDN="";
    while (@ASN1SubjectDNIndex) {
      my ($CLASS,$CONSTRUCTED,$TAG,$HEADSTART,$HEADLEN,$CHUNKLEN)=(0,0,0,0,0);
      until ($TAG == 6 ) { ($CLASS,$CONSTRUCTED,$TAG,$HEADSTART,$HEADLEN,$CHUNKLEN) = @{shift @ASN1SubjectDNIndex}; }
      my $OID=substr($X509subject,($HEADSTART+$HEADLEN),$CHUNKLEN);
      ($CLASS,$CONSTRUCTED,$TAG,$HEADSTART,$HEADLEN,$CHUNKLEN) = @{shift @ASN1SubjectDNIndex};
      my $Value=substr($X509subject,($HEADSTART+$HEADLEN),$CHUNKLEN);
      $SubjectDN.="/".VOMS::Lite::CertKeyHelper::OIDtoDNattrib(ASN1OIDtoOID($OID))."=$Value";
    }
    if ($UserIDN eq $SubjectDN) { debug("MATCHED CA",$SubjectDN); $GotCA=1; } 
    else                        { debug("        CA:", $SubjectDN); }
  }
  if ( @ReqASN1DN == 0 ) { ErrWarn(\@warning, "VOMS server does not tell me what CAs are supported"); }
  elsif ( $GotCA==0 )    { return { Errors => ErrWarn("VOMS server does not support your CA"), Warnings => \@warning }; }

#########################################################
#Talk to the server again

##Construct Certificate Message Record
  my $hexcertarray =""; 
  foreach my $cert (@chain) { $hexcertarray.=sprintf("%06s",DecToHex(length($cert))).Hex($cert);}
  my $hexcertobj      = sprintf("%06s",DecToHex(length($hexcertarray)/2)).$hexcertarray;
  my $hexcertmesg     = handShake("0b",$hexcertobj);
  my $hexcertsmessagerecord=recordLayer("16",$hexcertmesg);
  my $certmesg = pack("H*", $hexcertmesg); 

##ClientKeyExchange
#PreMasterSecret
  my $prernd='X' x 46;  $prernd =~ s/./chr(int(rand 256))/ge;
  my $hexpremastersecret='0300'.Hex($prernd);

#Derive Key Material
  my %KEYS=Keygen($hexpremastersecret,$hexrandom,Hex($sHelloTime.$sHelloRand));

#Make Client Key Exchange
  my $hexEncPMSecret   = rsaencrypt($hexpremastersecret,Hex($ServerCertInfo{'KeypublicExponent'}),Hex($ServerCertInfo{'Keymodulus'}));
  my $hexClientKeyExchange  = handShake("10",$hexEncPMSecret);    #### USE ME FOR CertificateVarify
  my $hexClientKeyExchangeMessageRecord = recordLayer("16",$hexClientKeyExchange);
  my $ClientKeyExchangeMessage = Bin($hexClientKeyExchange); #### ClientCertificate for handshakemessages needs to be without record layer

#CertificateVerify
  my $Hmsgs     = $clienthello.$serverhello.$certmesg.$ClientKeyExchangeMessage;
  my $verifymac = MAC($KEYS{'MS'},$Hmsgs);

  my $hexsignedcertificateverify        = rsasign($verifymac,$Keyexp,$Keymod);
  my $hexwrappedsignedcertificateverify = sprintf("%04s",DecToHex(length($hexsignedcertificateverify)/2)).$hexsignedcertificateverify;
  my $hexcertificateverify              = handShake('0f',$hexwrappedsignedcertificateverify);
  my $certificateverify                 = Bin($hexcertificateverify);
  my $hex_ssl_certificateverifyrecord   = recordLayer("16",$hexcertificateverify);

##########################################################################
## Switch to Encrypted Session -- change_cipher_spec message
#Select algorythm for key exchange -- Must be RSA
  my $hexkeyselection="140300000101";

# Switch to tripple des (the only one I support) and send finished message

  $Hmsgs.=$certificateverify;
  my $unechexfinished=handShake("14",MAC($KEYS{'MS'},$Hmsgs."CLNT"));

#Set up the Client and Server DES3-EDE sessions
  my $Ccipher = Crypt::CBC->new( -literal_key => 1, -padding => 'null', -key => $KEYS{'CK'},  -iv => $KEYS{'CIV'}, -header => 'none', -cipher => 'DES_EDE3' );
  my $Scipher = Crypt::CBC->new( -literal_key => 1, -padding => 'null', -key => $KEYS{'SK'},  -iv => $KEYS{'SIV'}, -header => 'none', -cipher => 'DES_EDE3' );
  my $Cseq=0;
  my $Sseq=0;

  my $hex_finishedrecord = &Encrypt(Bin(recordLayer("16",$unechexfinished)),$KEYS{'CMAC'},$pad1sha,$pad2sha,$Cseq,$Ccipher);
  my $hex_finished       = $hex_finishedrecord;
  $hex_finished         =~ s/^..........//s;
  my $finished           = Bin($hex_finished);

#############################################################################
#Send Records
  Write($sock,Bin($hexcertsmessagerecord.$hexClientKeyExchangeMessageRecord.$hex_ssl_certificateverifyrecord.$hexkeyselection.$hex_finishedrecord));

#############################################################################
#Receive Response
  $response=Read($sock);
  if ( $response =~ /^\x14\x03\x00\x00\x01\x01/ ) {  $response =~ s/......//; } #Change Cypher Spec -- what we expect
  else { return { Errors => ErrWarn("Error: Expecting SSL Change Cypher Spec Message, got something else."), Warnings => \@warning }; }
  my $serverfinishedhex=Hex(&Decrypt($response,$KEYS{'SMAC'},$pad1sha,$pad2sha,$Sseq,$Scipher));

# Check response from server is a valid finished message
  $Hmsgs.=Bin($unechexfinished);
  my $unencryptedfinishedmsg = handShake("14",MAC($KEYS{'MS'},$Hmsgs."SRVR"));
  if ($unencryptedfinishedmsg ne $serverfinishedhex) { return { Errors => ErrWarn("Failed to decrypt Server Finished Message"), Warnings => \@warning }; }

######################### 
# Send no delegation byte
# predata and postdata to stop TLS CBC IV attack
  my $predata      = Bin(&Encrypt(Bin("1703000000"),$KEYS{'CMAC'},$pad1sha,$pad2sha,$Cseq,$Ccipher));
  my $msg='0';
  my $emesg        = &Encrypt(Bin(recordLayer("17",Hex($msg))),$KEYS{'CMAC'},$pad1sha,$pad2sha,$Cseq,$Ccipher);
  $senddata        = Bin($emesg);
  my $postdata     = Bin(&Encrypt(Bin("1703000000"),$KEYS{'CMAC'},$pad1sha,$pad2sha,$Cseq,$Ccipher));

  Write($sock,$predata.$senddata.$postdata);

############## 
# Send request
#<xml version="1.0" encoding = "US-ASCII"?>
#  <voms>
#    <command>COMMAND</command>+
#    <order>ORDER</order>?
#    <targets>TARGETS</targets>?
#    <lifetime>N</lifetime>?
#    <base64>B</base64>?



( run in 0.813 second using v1.01-cache-2.11-cpan-71847e10f99 )