-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
- Loading branch information
Showing
2 changed files
with
247 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
''', | ||
) |