Skip to content

Commit

Permalink
First CLI implementation
Browse files Browse the repository at this point in the history
Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
  • Loading branch information
szszszsz committed Jun 1, 2017
1 parent 06c0deb commit b964508
Show file tree
Hide file tree
Showing 2 changed files with 247 additions and 0 deletions.
232 changes: 232 additions & 0 deletions unittest/libnitrokey.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
#!/usr/bin/env python

"""
Use the following to run locally:
$ sudo pip install virtualenv
$ virtualenv venv
$ . venv/bin/activate
$ pip install --editable .
$ libnitrokey --help
"""

import click
import itertools
import cffi

ffi = cffi.FFI()

gs = ffi.string
device_type = None


def connect():
fp = '../NK_C_API.h'

declarations = []
with open(fp, 'r') as f:
declarations = f.readlines()

a = iter(declarations)
for declaration in a:
if declaration.startswith('NK_C_API'):
declaration = declaration.replace('NK_C_API', '').strip()
while not ';' in declaration:
declaration += (next(a)).strip()
ffi.cdef(declaration, override=True)

C = None
import os, sys

path_build = [".", os.path.join(".", "build"), os.path.join("..", "build")]
names = ["libnitrokey-log.so", "libnitrokey.so"]
paths = itertools.product(path_build, names)
tested = []
for p in paths:
p = os.path.join(p[0], p[1])
tested.append(p)
if os.path.exists(p):
C = ffi.dlopen(p)
break
if not C:
print("No library file found")
print("Tested paths:" + repr(tested))
sys.exit(1)

C.NK_set_debug(False)

nk_login = C.NK_login_auto()
if nk_login != 1:
print('No devices detected!')
assert nk_login != 0 # returns 0 if not connected or wrong model or 1 when connected
global device_type
firmware_version = C.NK_get_major_firmware_version()
model = 'P' if firmware_version in [7, 8] else 'S'
device_type = (model, firmware_version)

# assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK
# assert C.NK_user_authenticate(DefaultPasswords.USER, DefaultPasswords.USER_TEMP) == DeviceErrorCode.STATUS_OK

# C.NK_status()

C.NK_set_debug(True)
return C


C = connect()


@click.group()
@click.option('--debug', default=0, help='debug level')
def cli(debug):
C.NK_set_debug(debug != 0)
pass


@click.command()
def status():
"""Show device's status"""
print (gs(C.NK_status()))
if device_type[0] == 'S':
print (gs(C.NK_get_status_storage_as_string()))
return C.NK_get_last_command_status()


@click.command()
def device_serial_number():
"""Show device's serial number"""
print (gs(C.NK_device_serial_number()))
return C.NK_get_last_command_status()


def abort_callback(ctx, param, value):
if not value:
ctx.abort()


@click.command()
@click.option('--yes', is_flag=True, callback=abort_callback,
expose_value=False, prompt='Do you want to continue?')
def lock_device():
"""Lock the device - lock volumes and password safe"""
print C.NK_lock_device() or "Locked"
return C.NK_get_last_command_status()


#
# @click.command()
# def NK_first_authenticate():
# """Show device status"""
# print C.NK_first_authenticate()
# return C.NK_get_last_command_status()
#
#
# @click.command()
# def NK_user_authenticate():
# """Show device status"""
# print C.NK_user_authenticate()
# return C.NK_get_last_command_status()


# @click.command()
# def NK_factory_reset():
# """Show device status"""
# print C.NK_factory_reset()
# return C.NK_get_last_command_status()
#
#
# @click.command()
# def NK_build_aes_key():
# """Show device status"""
# print C.NK_build_aes_key()
# return C.NK_get_last_command_status()
#
#
# @click.command()
# @click.argument('slot_number')
# def NK_unlock_user_password(slot_number):
# """Show device status"""
# print C.NK_unlock_user_password()
# return C.NK_get_last_command_status()


@click.command()
@click.argument('slot_number')
def get_totp_slot_name(slot_number):
"""Show TOTP slot name"""
print gs(C.NK_get_totp_slot_name(int(slot_number))) or "OTP slot not programmed"
return C.NK_get_last_command_status()


@click.command()
@click.argument('slot_number')
def get_hotp_slot_name(slot_number):
"""Show HOTP slot name"""
print gs(C.NK_get_hotp_slot_name(int(slot_number))) or "OTP slot not programmed"
return C.NK_get_last_command_status()


#
# @click.command()
# def NK_erase_hotp_slot():
# """Show device status"""
# print C.NK_erase_hotp_slot()
# return C.NK_get_last_command_status()
#
#
# @click.command()
# def NK_erase_totp_slot():
# """NK_erase_totp_slot"""
# print C.NK_erase_totp_slot()
# return C.NK_get_last_command_status()


@click.command()
@click.argument('slot_number')
def get_hotp_code(slot_number):
"""Get HOTP code"""
print gs(C.NK_get_hotp_code(int(slot_number))) or "OTP slot not programmed"
return C.NK_get_last_command_status()


@click.command()
@click.argument('slot_number')
def get_totp_code(slot_number):
"""Get TOTP code"""
print gs(C.NK_get_totp_code(int(slot_number), 0, 0, 0)) or "OTP slot not programmed"
return C.NK_get_last_command_status()


@click.command()
@click.option('--user_pin', prompt=True, confirmation_prompt=True,
hide_input=True)
def unlock_encrypted_volume(user_pin):
"""Unlock encrypted volume"""
print C.NK_unlock_encrypted_volume(str(user_pin)) or "Unlocked"
return C.NK_get_last_command_status()


@click.command()
@click.option('--hidden_volume_password', prompt=True, confirmation_prompt=True,
hide_input=True)
def unlock_hidden_volume(hidden_volume_password):
"""Unlock hidden volume"""
print C.NK_unlock_hidden_volume(str(hidden_volume_password)) or "Unlocked"
return C.NK_get_last_command_status()


cli.add_command(status)
cli.add_command(device_serial_number)
cli.add_command(lock_device)
cli.add_command(unlock_encrypted_volume)
cli.add_command(unlock_hidden_volume)

cli.add_command(get_hotp_code)
cli.add_command(get_totp_code)
cli.add_command(get_hotp_slot_name)
cli.add_command(get_totp_slot_name)

if __name__ == '__main__':
cli()
C.NK_logout()

15 changes: 15 additions & 0 deletions unittest/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from setuptools import setup

setup(
name='libnitrokey',
version='0.1',
py_modules=['libnitrokey'],
install_requires=[
'Click',
'cffi',
],
entry_points='''
[console_scripts]
libnitrokey=libnitrokey:cli
''',
)

0 comments on commit b964508

Please sign in to comment.