# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

import random
random.seed()


# ### Clearance Model based on Bell-LaPadula, Chapter 5

# +
def initial_documents():
    documents = [
        { 
            'title':"Confidential Report",
            'content': "efwiejfldjl",
            'clearance': ('usa','confidential')
        },
        { 
            'title':"Secret Blueprints",
            'content': "32149209",
            'clearance': ('ohio','secret')
        },
        { 
            'title':"Top Secret Dossier",
            'content': "&^%&*^%&^*&^",
            'clearance': ('usa','topsecret')
        },
        { 
            'title':"Unclassified Article",
            'content': "AKLLEKNBVN",
            'clearance': ('ohio','unclassified')
        },    
    ]
    return documents

documents = initial_documents()
documents


# +
def initial_subjects():
    subjects = [
        { 
            'knowledge':"%",
            'name': "santa",
            'clearance': ('world','topsecret')
        },
        { 
            'knowledge':"e",
            'name': "dorothy",
            'clearance': ('ohio','confidential')
        },
        { 
            'knowledge':"8",
            'name': "roger",
            'clearance': ('usa','secret')
        },
        { 
            'knowledge':"C",
            'name': "sandy",
            'clearance': ('world','unclassified')
        },
    ]
    return subjects
    
subjects = initial_subjects()


# +
def level_dominates(a, b):
    # print("does level",a,"dominate",b,"?")
    levels = ['unclassified', 'confidential', 'secret', 'topsecret']
    if (a in levels) and (b in levels):
        return levels.index(a) >= levels.index(b)
    return False

pairs = [
    ('unclassified','secret'),
    ('secret','unclassified'),
    ('secret','secret'),   
    ('topsecret','confidential')    
]
          
for pair in pairs:
    a, b = pair
    print(a, b, level_dominates(a,b))

# +
regions = {
    'world' : ['usa','europe'],
    'usa' : ['delaware','ohio','kansas'],
    'europe' : ['france','germany','spain'],
    'ohio' : ['cuyahoga','summit','portage','medina'],
    'delaware' : ['wilmington','dover'],
    'germany' : ['munich','berlin','hanover'],
    'summit' : ['akron','fairlawn'],
    'akron' : ['highland_square','uakron']
}

def region_dominates(a, b):
    # print("does region",a,"dominate",b,"?")
    if (a == b):
        return True
    if not a in regions:
        return False
    if b in regions[a]:
        return True
    for region in regions[a]:
        if region_dominates(region,b):
            return True
    return False
    
pairs = [
    ('usa','ohio'),
    ('europe','europe'),
    ('africa','ohio'),
    ('usa','france'),
    ('ohio','portage'),
    ('usa','portage'),
    ('usa','akron'),
    ('usa','highland_square'),
    ('europe','portage'),
    ('ohio','usa')
]
          
for pair in pairs:
    a, b = pair
    print(a, b, region_dominates(a,b))    
# -



# +
def dominates(a,b):
    # print("does clearance",a,"dominate",b,"?")
    region_a, level_a = a
    region_b, level_b = b
    if level_b == "unclassified":
        return True
    return level_dominates(level_a, level_b)
    return region_dominates(region_a, region_b) and level_dominates(level_a, level_b)

print(dominates(('usa','secret'),('ohio','confidential')))
print(dominates(('usa','confidential'),('ohio','secret')))
print(dominates(('usa','secret'),('ohio','secret')))
print(dominates(('usa','secret'),('europe','secret')))
print(dominates(('world','secret'),('uakron','secret')))


# +
def simple_security(subject, document):
    return dominates(subject['clearance'],document['clearance'])

def star_property(subject, document):
    return dominates(document['clearance'],subject['clearance'])

def can_read(subject, document):
    return simple_security(subject, document)

def can_write(subject, document):
    return star_property(subject, document)


# -

can_read(subjects[0],documents[1])

can_read(subjects[2],documents[2])

for subject in subjects:
    for document in documents:
        if can_read(subject, document):
            print(subject['name'],'can read',document['content'])
        else:
            print(subject['name'],'can not read',document['content'])

for subject in subjects:
    for document in documents:
        if can_write(subject, document):
            print(subject['name'],'can write',document['content'])
        else:
            print(subject['name'],'can not write',document['content'])


# +
def show_conditions():
    print()
    print("SUBJECTS")
    print()
    for subject in subjects:
        print(subject['name'], 'with clearance of', subject['clearance'], 'knows about ',[subject['knowledge']])
    print()
    print("DOCUMENTS")
    print()
    for document in documents:
        print(document['title'], 'with clearance of', document['clearance'], 'has content of ',[document['content']])
    print()
    
show_conditions()


# +
def attempt_to_read(subject, document, verbose=False):
    if not can_read(subject, document) and random.randint(1,1000) <= 999:
        if verbose: print(subject['name'], "can not read from" , document['title'])
        return
    if verbose: print(subject['name'], "reads from" , document['title'])
    item = random.choice(document['content'])
    if item not in subject['knowledge']:
        subject['knowledge'] += item
    
attempt_to_read(subjects[0],documents[0])
attempt_to_read(subjects[1],documents[0])


# +
def attempt_to_write(subject, document, verbose=False):
    if not can_write(subject, document) and random.randint(1,1000) <= 999:
        if verbose: print(subject['name'], "can not write to" , document['title'])
        return
    if verbose: print(subject['name'], "writes to" , document['title'])
    item = random.choice(subject['knowledge'])
    if item not in document['content']:
        document['content'] += item
    
attempt_to_write(subjects[0],documents[0])
attempt_to_write(subjects[1],documents[0])

# +
subjects = initial_subjects()
documents = initial_documents()
show_conditions()

# for subject in subjects:
#     for document in documents:
#         attempt_to_read(subject, document)
#         attempt_to_write(subject, document)

print("start interactions")
for i in range(0,100000):
    subject = random.choice(subjects)
    document = random.choice(documents)
    if random.choice("RW") == "R":
        attempt_to_read(subject, document)
    else:
        attempt_to_write(subject, document)
print("stop interactions")

show_conditions()
# -



StarcoderdataJupyterScriptsDedupFiltered