Issuing a License in a License Chain

banner art

Previous Next

Issuing a License in a License Chain

When issuing licenses for a license chain, the issuer might need to issue an entire license chain or only elements of the chain. So, the license issuer needs to know which license elements to issue.

The content header contains the uplink ID (the root key ID) in the license chain, which is also included in the license request. Use the WMRMChallenge.Uplinks property to retrieve this information from the license request. A WMRMUplinkCollection ** object is returned, and it contains a collection that corresponds to the elements in the license chain (item 0 is the leaf license, item 1 is the root license.) You can iterate through the collection and retrieve information into a WMRMUplink object, which provides the key ID and license state data for each license element. The license state data in the WMRMLicenseStateData object provides information about the licenses that are already present on the client computer, such as expiration dates and remaining play counts. Using this information, the license issuer can determine which elements in the license chain need to be reissued. For example, if the root license has expired but the leaf license is still valid, only a root license needs to be reissued.

When you issue a license from a license chain, you issue it almost as you would a simple license. The root license is bound to the computer, but the leaf license is bound to the root license by specifying the root key and key ID in the leaf license by using the WMRMLicGen.UplinkKey and WMRMLicGen.UplinkKid properties.

Additionally, rather than the 7-byte key used for simple or leaf licenses, the root licenses in a chain require a key of 8 bytes, which must be created using the WMRMKeys.GenerateKeyEx method.

Example Code

The following example is based on the sample page Simple.asp in the C:\WMSDK\WMRM10.1\samples folder, but this sample can issue a simple or a chained license depending on the license request.

<%@ LANGUAGE="VBScript"%>
<%
Response.Buffer = True
Response.Expires = 0
Do
    On Error Resume Next

'"""""""""""""""""""""""""""""""""""""""""""""""""""""
' Declare variables.
'"""""""""""""""""""""""""""""""""""""""""""""""""""""
    Dim ChallengeObj             ' WMRMChallenge object
    Dim ChainCollObj             ' WMRMUplinkCollection object
    Dim ChainObj                 ' WMRMUplink object
    Dim LeafLicenseStateObj      ' WMRMLicenseStateData object
    Dim RootLicenseStateObj      ' WMRMLicenseStateData object
    Dim HeaderObj                ' WMRMHeader object
    Dim KeyObj                   ' WMRMKeys object
    Dim RightsObj                ' WMRMRights object
    Dim LicenseObj               ' WMRMLicGen object
    Dim ResponseObj              ' WMRMResponse object
    Dim RestrictObj              ' WMRMRestrictions object

    Dim ContentServerPubKey      ' Public key of the content server
    Dim Seed                     ' License key seed
    Dim Delivery                 ' Delivery flag
    Dim LicChain                 ' License chain flag
    Dim Silent                   ' Silent delivery flag
    Dim strLicenseRequested      ' License request string
    Dim varClientInfo            ' Client information
    Dim varHeader                ' Content header
    Dim blnResult                ' Signature verification
    Dim SimpleLeafKID            ' Key ID of a simple license or leaf license
    Dim IndiVersion              ' Security version of the DRM component
    Dim strRevinfo               ' Revocation information string
    Dim ContainsRevinfo          ' Flag for revocation information
    Dim strClientCRLs            ' Supported revocation lists string

    Dim RootKID                  ' Key ID of the root license
    Dim RootCat                  ' License state data for root licenses
    Dim RCountArray              ' Count array
    Dim RDateArray               ' Date array
    Dim RStreamID                ' Stream ID
    Dim RVague                   ' Vagueness
    Dim IssueRoot                ' Root license flag
    Dim Rcounts                  ' Remaining counts
    Dim RstartDate               ' Start date
    Dim RExpDate                 ' Expiration date

    Dim LeafCat                  ' License state data for leaf licenses
    Dim LCountArray              ' Count array
    Dim LDateArray               ' Date array
    Dim LStreamID                ' Stream ID
    Dim LVague                   ' Vagueness
    Dim IssueLeaf                ' Leaf license flag
    Dim Lcounts                  ' Remaining counts
    Dim LstartDate               ' Start date
    Dim LExpDate                 ' Expiration date

    Dim SimpleLeafKey            ' Key for the simple license or leaf license
    Dim SimpleLeafRights         ' Rights string for the simple license or leaf license
    Dim SimpleLeafLicense        ' License for the simple license or leaf license

    Dim RootKey                  ' Key for the root license
    Dim RootRights               ' Rights string for the root license
    Dim RootLicense              ' Root license

    Dim LicResponse              ' License response

'"""""""""""""""""""""""""""""""""""""""""""""""""""""
' Set variables.
'"""""""""""""""""""""""""""""""""""""""""""""""""""""
    ContentServerPubKey = Application("contentserverpubkey")
    Seed = Application("seed")
    Delivery = ""
    LicChain = ""
    Silent = True

'"""""""""""""""""""""""""""""""""""""""""""""""""""""
' Check the request for silent or non-silent delivery.
'"""""""""""""""""""""""""""""""""""""""""""""""""""""
    If (Request.Form("nonsilent") <> "") Then Silent = False

'"""""""""""""""""""""""""""""""""""""""""""""""""""""
' Retrieve the license request. Get the client information and content header.
'"""""""""""""""""""""""""""""""""""""""""""""""""""""
    Set ChallengeObj = Server.CreateObject("WMRMObjs.WMRMchallenge")
    strLicenseRequested = Request.Form("challenge")
    ChallengeObj.Challenge = strLicenseRequested
    varClientInfo = ChallengeObj.ClientInfo
    varHeader = ChallengeObj.Header

'"""""""""""""""""""""""""""""""""""""""""""""""""""""
' Check for revocation information.
'"""""""""""""""""""""""""""""""""""""""""""""""""""""
    strRevinfo = ChallengeObj.RevInfo
    ContainsRevinfo = ChallengeObj.RevInfoPresent

'"""""""""""""""""""""""""""""""""""""""""""""""""""""
' Put the content header into the header object. Retrieve
' the KID and required individualization version.
'"""""""""""""""""""""""""""""""""""""""""""""""""""""
    Set HeaderObj = Server.CreateObject("WMRMObjs.WMRMheader")
    HeaderObj.Header = varHeader
    blnResult = HeaderObj.Verify(ContentServerPubKey)
    SimpleLeafKID = HeaderObj.KeyID
    IndiVersion = HeaderObj.IndividualizedVersion
        ' If IndividualizedVersion is not specified, an error 
        ' might be set.

'"""""""""""""""""""""""""""""""""""""""""""""""""""""
' If this is a chained license, retrieve the root license KID.
'"""""""""""""""""""""""""""""""""""""""""""""""""""""
    Set ChainCollObj = ChallengeObj.Uplinks
    If (Err.Number = 0) Then    ' Request for a license chain. 
        LicChain = "chain"     

        ' Get license state data and key ID for the root license.
        Set ChainObj = ChainCollObj.item(1)
        RootKID =  ChainObj.KID

        ' Get license state data to determine whether to issue
        ' a root license.
        Set RootLicenseStateObj = ChainObj.LicenseState
        RootCat = cstr(RootLicenseStateObj.Category)
        Select Case RootCat
            case 0    ' The root license has no rights.
                IssueRoot = True
            case 1    ' The root license has unlimited play counts.
                IssueRoot = False
            case 2    ' The root license has remaining play counts.
                RCountArray = RootLicenseStateObj.Counts 
                RCounts = cstr(RCountArray(0))
                IssueRoot = False
            case 3    ' The root license has a start date.
                RDateArray = RootLicenseStateObj.Dates
                RStartDate =  cstr(RDateArray(0))
                IssueRoot = False
            case 4    ' The root license has an expiration date.
                RDateArray = RootLicenseStateObj.Dates
                RExpDate =  cstr(RDateArray(0))
                IssueRoot = False
            case 5    ' The root license has start and expiration dates.
                RDateArray = RootLicenseStateObj.Dates
                RStartDate =  cstr(RDateArray(0))
                RExpDate =  cstr(RDateArray(1))
                IssueRoot = False
            case 6    ' The root license has a start date and 
                      ' remaining play counts.
                RDateArray = RootLicenseStateObj.Dates
                RStartDate =  cstr(RDateArray(0))
                RCountArray = RootLicenseStateObj.Counts 
                RCounts = cstr(RCountArray(0))
                IssueRoot = False
            case 7    ' The root license has an expiration date and 
                      ' remaining play counts.
                RDateArray = RootLicenseStateObj.Dates
                RExpDate =  cstr(RDateArray(0))
                RCountArray = RootLicenseStateObj.Counts 
                RCounts = cstr(RCountArray(0))
                IssueRoot = False
            case 8    ' The root license has start and expiration 
                      ' dates, and remaining play counts.
                RDateArray = RootLicenseStateObj.Dates
                RStartDate =  cstr(RDateArray(0))
                RExpDate =  cstr(RDateArray(1))
                RCountArray = RootLicenseStateObj.Counts 
                RCounts = cstr(RCountArray(0))
                IssueRoot = False
            case 9    ' The root license expires after first use.
                IssueRoot = False
        End Select

        RStreamID = RootLicenseStateObj.StreamID  ' This value is always 0.
        RVague = RootLicenseStateObj.Vagueness

        ' Get license state data to determine whether to issue
        ' a leaf license.
        Set ChainObj = ChainCollObj.item(0)
        Set LeafLicenseStateObj = ChainObj.LicenseState
        LeafCat = cstr(LeafLicenseStateObj.Category)
        Select Case LeafCat
            case 0    ' The leaf license has no rights.
                IssueLeaf = True
            case 1    ' The leaf license has unlimited play counts.
                IssueLeaf = False
            case 2    ' The leaf license has remaining play counts.
                LCountArray = LeafLicenseStateObj.Counts 
                LCounts = cstr(LCountArray(0))
                IssueLeaf = False
            case 3    ' The leaf license has a start date.
                LDateArray = LeafLicenseStateObj.Dates
                LStartDate =  cstr(LDateArray(0))
                IssueLeaf = False
            case 4    ' The leaf license has an expiration date.
                LDateArray = LeafLicenseStateObj.Dates
                LExpDate =  cstr(LDateArray(0))
                IssueLeaf = False
            case 5    ' The leaf license has start and expiration dates.
                LDateArray = LeafLicenseStateObj.Dates
                LStartDate =  cstr(LDateArray(0))
                LExpDate =  cstr(LDateArray(1))
                IssueLeaf = False
            case 6    ' The leaf license has a start date and 
                      ' remaining play counts.
                LDateArray = LeafLicenseStateObj.Dates
                LStartDate =  cstr(LDateArray(0))
                LCountArray = LeafLicenseStateObj.Counts 
                LCounts = cstr(LCountArray(0))
                IssueLeaf = False
            case 7    ' The leaf license has an expiration date and 
                      ' remaining play counts.
                LDateArray = LeafLicenseStateObj.Dates
                LExpDate =  cstr(LDateArray(0))
                LCountArray = LeafLicenseStateObj.Counts 
                LCounts = cstr(LCountArray(0))
                IssueLeaf = False
            case 8    ' The leaf license has start and expiration 
                      ' dates, and remaining play counts.
                LDateArray = LeafLicenseStateObj.Dates
                LStartDate =  cstr(LDateArray(0))
                LExpDate =  cstr(LDateArray(1))
                LCountArray = LeafLicenseStateObj.Counts 
                LCounts = cstr(LCountArray(0))
                IssueLeaf = False
            case 9    ' The root license expires after first use.
                IssueLeaf = False
        End Select

        LStreamID = LeafLicenseStateObj.StreamID  ' This value is always 0.
        LVague = LeafLicenseStateObj.Vagueness

    Else    ' An error indicates a request for a simple license.
        err.clear
        LicChain = "simple"
    End If

'"""""""""""""""""""""""""""""""""""""""""""""""""""""
' Generate the keys.
'"""""""""""""""""""""""""""""""""""""""""""""""""""""
    Set KeyObj = Server.CreateObject("WMRMObjs.WMRMkeys")
    KeyObj.KeyID = SimpleLeafKID
    KeyObj.Seed = Seed

    ' This is a key for either a simple license or a leaf license.
    SimpleLeafKey = KeyObj.GenerateKey() 

    If (LicChain = "chain") Then  ' Generate the 8-byte key for the root license.
            KeyObj.KeyID = RootKID
            RootKey = KeyObj.GenerateKeyEx(8)
    End If

'"""""""""""""""""""""""""""""""""""""""""""""""""""""
' Get the certificate revocation lists that are supported by the client.
'"""""""""""""""""""""""""""""""""""""""""""""""""""""
    strClientCRLs = LicGenObj.SupportedCRLS

'"""""""""""""""""""""""""""""""""""""""""""""""""""""
' Set the rights.
'"""""""""""""""""""""""""""""""""""""""""""""""""""""
    Set RightsObj = Server.CreateObject("WMRMObjs.WMRMRights")

    If (LicChain = "simple") Then  ' Generate rights for a simple license.
        RightsObj.Playcount = 2
        RightsObj.AllowCopy = True
        RightsObj.CopyCount = 5
        RightsObj.AllowCollaborativePlay = False
        RightsObj.AllowBackupRestore = False
        RightsObj.AllowPlaylistBurn = True
        RightsObj.MaxPlaylistBurnCount = 5
        RightsObj.PlaylistBurnTrackCount = 15
        RightsObj.MinimumClientSDKSecurity = 3000
        RightsObj.MinimumSecurityLevel = 1000
        RightsObj.GracePeriod = 24

        RightsObj.ExpirationDate = "#20051231Z#"
        RightsObj.DeleteOnClockRollback = False
        RightsObj.DisableOnClockRollback = True

        ' Set copy restrictions.
        Set RestrictObj = Server.CreateObject("WMRMObjs.WMRMRestrictions")
        Call RestrictObj.AddRestriction(6, 400)
        RightsObj.CopyRestrictions = RestrictObj.GetRestrictions

        If Err.Number = 0 Then
            SimpleLeafRights = RightsObj.GetAllRights
        End If

    Else
        ' Generate rights for a leaf license.
        RightsObj.AllowCopy = True
        RightsObj.CopyCount = 5
        RightsObj.AllowCollaborativePlay = False
        RightsObj.AllowBackupRestore = False
        RightsObj.AllowPlaylistBurn = True
        RightsObj.MaxPlaylistBurnCount = 5
        RightsObj.PlaylistBurnTrackCount = 15
        RightsObj.GracePeriod = 24
        RightsObj.MinimumClientSDKSecurity = 3000
        RightsObj.MinimumSecurityLevel = 1000

        ' Set copy restrictions.
        Set RestrictObj = Server.CreateObject("WMRMObjs.WMRMRestrictions")
        Call RestrictObj.AddRestriction(6, 400)
        RightsObj.CopyRestrictions = RestrictObj.GetRestrictions

        ' Get the rights string.
        If Err.Number = 0 Then
            SimpleLeafRights = RightsObj.GetAllRights
        End If

      ' Generate rights for a root license.
        RightsObj.Reset
        RightsObj.Playcount = 1
        RightsObj.AllowCopy = True
        RightsObj.AllowPlaylistBurn = True
        RightsObj.AllowCollaborativePlay = False
        RightsObj.AllowBackupRestore = False

        RightsObj.ExpirationDate = "#20051231Z#"
        RightsObj.DeleteOnClockRollback = False
        RightsObj.DisableOnClockRollback = True

        ' Set copy restrictions.
        RightsObj.CopyRestrictions = RestrictObj.GetRestrictions

        ' Get the rights string.
        If Err.Number = 0 Then
            RootRights = RightsObj.GetAllRights
        End If

    End If

'"""""""""""""""""""""""""""""""""""""""""""""""""""""
' Generate a simple license or leaf license.
'"""""""""""""""""""""""""""""""""""""""""""""""""""""
    Set LicenseObj = Server.CreateObject("WMRMObjs.WMRMlicgen")
    LicenseObj.KeyID = SimpleLeafKID
    LicenseObj.SetKey "", SimpleLeafKey
    LicenseObj.Priority = 10
    LicenseObj.Rights = SimpleLeafRights
    LicenseObj.ClientInfo = varClientInfo
    LicenseObj.BindToPubKey = ContentServerPubKey
    LicenseObj.Attribute("ContentDistributor") = "Distributor Name"
    LicenseObj.IndividualizedVersion = IndiVersion

    If (LicChain = "chain") Then   ' Link to the root license.
        LicenseObj.UplinkKid = RootKID
        LicenseObj.UplinkKey = RootKey
    End If

    SimpleLeafLicense = LicenseObj.GetLicenseToDeliver()
    Delivery = "deliver"

'"""""""""""""""""""""""""""""""""""""""""""""""""""""
'Generate a root license.
'"""""""""""""""""""""""""""""""""""""""""""""""""""""
    If (LicChain = "chain") Then
        Set LicenseObj = Nothing
        Set LicenseObj = Server.CreateObject("WMRMObjs.WMRMlicgen")
        LicenseObj.KeyID = RootKID
        LicenseObj.SetKey "", RootKey
        LicenseObj.Priority = 10
        LicenseObj.Rights = RootRights
        LicenseObj.ClientInfo = varClientInfo
        LicenseObj.BindToPubKey = ContentServerPubKey
        LicenseObj.Attribute("ContentDistributor") = "Distributor Name"
        LicenseObj.IndividualizedVersion = IndiVersion
        RootLicense = LicenseObj.GetLicenseToDeliver()
    End If

Loop While False

'"""""""""""""""""""""""""""""""""""""""""""""""""""""
' Send an error message or deliver the license.
'"""""""""""""""""""""""""""""""""""""""""""""""""""""
  If (Delivery = "" and Err.Number <> 0) Then
        Response.Write "0x" + cstr(hex(err.number)) + " :" & Err.Description

  ElseIf (Delivery = "deliver") Then
    Set ResponseObj = Server.CreateObject("WMRMObjs.WMRMresponse")

    If (LicChain = "simple") or (IssueLeaf = True) Then
        ' Include a simple license or leaf license in the license response.
        Call ResponseObj.AddLicense("2.0.0.0", SimpleLeafLicense)
    End If

    If (IssueRoot = True) Then 
        ' Include the root license in the license response.
        Call ResponseObj.AddLicense("2.0.0.0", RootLicense)
    End If

    Call ResponseObj.AddRevocationData(strRevinfo, strClientCRLs, ContainsRevinfo)

    If (Silent = True) Then
        LicResponse = ResponseObj.GetLicenseResponse()
        Response.Write LicResponse

    ElseIf (Silent = False) Then
      ' This replaces quotes to pass a value.
      ' ResponseObj.ReplaceQuotesWith = """"""    ' For VBScript.
        ResponseObj.ReplaceQuotesWith = "\"""     ' For JavaScript.
        LicResponse = ResponseObj.GetLicenseResponse()
%>
<!-- #include file="simple_ns.asp" -->
<%
    End If
  End If

' Clear objects.
    Set ChallengeObj = Nothing
    Set ChainCollObj = Nothing
    Set ChainObj = Nothing
    Set LicenseStateObj = Nothing
    Set HeaderObj = Nothing
    Set KeyObj = Nothing
    Set RightsObj = Nothing
    Set LicenseObj = Nothing
    Set ResponseObj = Nothing
%>

See Also

Previous Next

© 2007 Microsoft Corporation. All rights reserved.