Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Marcus Pedersén
nkey-pro
Commits
81fd7cff
Commit
81fd7cff
authored
Dec 20, 2018
by
Marcus Pedersén
Browse files
Added functionality to erase slot
parent
e08fb6f4
Changes
1
Hide whitespace changes
Inline
Side-by-side
src/main.rs
View file @
81fd7cff
...
...
@@ -25,7 +25,7 @@ extern crate rpassword;
extern
crate
chrono
;
use
clap
::{
Arg
,
App
,
ArgMatches
};
use
nitrokey
::{
Device
,
Pro
,
GenerateOtp
,
Authenticate
};
use
nitrokey
::{
Device
,
Pro
,
GenerateOtp
,
ConfigureOtp
,
Authenticate
};
use
chrono
::
Local
;
use
std
::
process
::
exit
;
use
std
::
collections
::
HashMap
;
...
...
@@ -89,6 +89,19 @@ fn main() {
Err
(
_
)
=>
exit
(
1
),
}
}
else
if
matches
.is_present
(
"ERASETOTP"
)
{
match
erase_slot
(
device
,
CodeType
::
Totp
)
{
Ok
(
_
)
=>
(),
Err
(
_
)
=>
exit
(
1
),
}
}
else
if
matches
.is_present
(
"ERASEHOTP"
)
{
match
erase_slot
(
device
,
CodeType
::
Hotp
)
{
Ok
(
_
)
=>
(),
Err
(
_
)
=>
exit
(
1
),
}
}
}
...
...
@@ -168,13 +181,13 @@ fn get_code( device: Pro, ctype: CodeType) -> Result<(), ()> {
let
slot_no
;
if
ctype
==
CodeType
::
Totp
{
slot_no
=
match
get_slot_from_user
(
CodeType
::
Totp
)
{
slot_no
=
match
get_slot_from_user
(
&
CodeType
::
Totp
)
{
Ok
(
n
)
=>
n
,
Err
(
_
)
=>
return
Err
(()),
};
}
else
{
slot_no
=
match
get_slot_from_user
(
CodeType
::
Hotp
)
{
slot_no
=
match
get_slot_from_user
(
&
CodeType
::
Hotp
)
{
Ok
(
n
)
=>
n
,
Err
(
_
)
=>
return
Err
(()),
};
...
...
@@ -311,14 +324,14 @@ fn get_code( device: Pro, ctype: CodeType) -> Result<(), ()> {
/// that value is within valid values
/// Different values if totp or hotp
/// Returns chosen slot
fn
get_slot_from_user
(
t
:
CodeType
)
->
Result
<
u8
,
()
>
{
fn
get_slot_from_user
(
t
:
&
CodeType
)
->
Result
<
u8
,
()
>
{
let
mut
got_slot
=
false
;
let
mut
slot_no
:
u8
=
0
;
while
!
got_slot
{
println!
(
""
);
if
t
==
CodeType
::
Totp
{
if
*
t
==
CodeType
::
Totp
{
println!
(
"Number of slot to get (1-15): "
);
}
else
{
...
...
@@ -344,7 +357,7 @@ fn get_slot_from_user(t: CodeType) -> Result<u8, ()> {
},
}
if
t
==
CodeType
::
Totp
{
if
*
t
==
CodeType
::
Totp
{
if
slot_no
>
15
||
slot_no
<
1
{
eprintln!
(
"Integer must be between 1 and 15"
);
continue
;
...
...
@@ -519,6 +532,85 @@ fn unlock_user_pin(device: Pro) -> Result<(), ()> {
Ok
(())
}
/// Erase slot from Nitrokey Pro
/// Totp or hotp is given as argument
fn
erase_slot
(
device
:
Pro
,
t
:
CodeType
)
->
Result
<
(),
()
>
{
let
mut
got_pin
=
false
;
let
mut
adm_pw
:
String
=
String
::
new
();
let
no_admin_retry
=
device
.get_admin_retry_count
();
println!
(
"{} remaining authentication attempts (admin)"
,
no_admin_retry
);
while
!
got_pin
{
adm_pw
=
match
rpassword
::
prompt_password_stdout
(
"Admin PIN: "
)
{
Ok
(
p
)
=>
p
,
Err
(
e
)
=>
{
eprintln!
(
"Error getting PIN from user: {}"
,
e
.to_string
());
return
Err
(());
},
};
let
pw_split
:
Vec
<&
str
>
=
adm_pw
.matches
(
char
::
is_numeric
)
.collect
();
if
adm_pw
.len
()
!=
pw_split
.len
()
{
eprintln!
(
"Error PIN is not only numeric, try again"
);
continue
;
}
got_pin
=
true
;
}
match
device
.authenticate_admin
(
adm_pw
.as_str
())
{
Ok
(
admin
)
=>
{
if
let
Ok
(
slot
)
=
get_slot_from_user
(
&
t
)
{
println!
(
"Are you sure that you want to erase slot number {}: [Y/N]?"
,
slot
+
1
);
let
mut
show_slot
=
String
::
new
();
match
io
::
stdin
()
.read_line
(
&
mut
show_slot
)
{
Ok
(
_
)
=>
(),
Err
(
e
)
=>
{
eprintln!
(
"Error reading from stdin: {}"
,
e
.to_string
());
return
Err
(());
},
}
show_slot
=
show_slot
.to_lowercase
();
if
show_slot
.trim
()
==
"y"
||
show_slot
.trim
()
==
"yes"
{
if
t
==
CodeType
::
Totp
{
match
admin
.erase_totp_slot
(
slot
)
{
Ok
(())
=>
println!
(
"Slot {} successfully erased"
,
slot
+
1
),
Err
(
e
)
=>
{
eprintln!
(
"Error erasing slot {}: {}"
,
slot
+
1
,
e
);
return
Err
(());
},
}
}
else
{
match
admin
.erase_hotp_slot
(
slot
)
{
Ok
(())
=>
println!
(
"Slot {} successfully erased"
,
slot
+
1
),
Err
(
e
)
=>
{
eprintln!
(
"Error erasing slot {}: {}"
,
slot
+
1
,
e
);
return
Err
(());
},
}
}
}
}
else
{
return
Err
(());
}
},
Err
(
e
)
=>
{
eprintln!
(
"Error authenticate admin: {:?}"
,
e
);
return
Err
(());
},
}
Ok
(())
}
/// Asks user for new PIN
/// Erro checks and returns
/// a valid PIN
...
...
@@ -595,33 +687,45 @@ fn arg_matches() -> ArgMatches<'static> {
.arg
(
Arg
::
with_name
(
"TOTP"
)
.short
(
"t"
)
.long
(
"totp"
)
.conflicts_with_all
(
&
[
"ADMINPIN"
,
"HOTP"
,
"USERPIN"
,
"UNLOCKPIN"
])
.conflicts_with_all
(
&
[
"ADMINPIN"
,
"HOTP"
,
"USERPIN"
,
"UNLOCKPIN"
,
"ERASETOTP"
,
"ERASEHOTP"
])
.takes_value
(
false
)
.help
(
"Get totp code"
))
.arg
(
Arg
::
with_name
(
"HOTP"
)
.short
(
"o"
)
.long
(
"hotp"
)
.conflicts_with_all
(
&
[
"ADMINPIN"
,
"TOTP"
,
"USERPIN"
,
"UNLOCKPIN"
])
.conflicts_with_all
(
&
[
"ADMINPIN"
,
"TOTP"
,
"USERPIN"
,
"UNLOCKPIN"
,
"ERASETOTP"
,
"ERASEHOTP"
])
.takes_value
(
false
)
.help
(
"Get hotp code"
))
.arg
(
Arg
::
with_name
(
"USERPIN"
)
.short
(
"u"
)
.long
(
"user-pin"
)
.conflicts_with_all
(
&
[
"TOTP"
,
"HOTP"
,
"ADMINPIN"
,
"UNLOCKPIN"
])
.conflicts_with_all
(
&
[
"TOTP"
,
"HOTP"
,
"ADMINPIN"
,
"UNLOCKPIN"
,
"ERASETOTP"
,
"ERASEHOTP"
])
.takes_value
(
false
)
.help
(
"Change user pin"
))
.arg
(
Arg
::
with_name
(
"ADMINPIN"
)
.short
(
"a"
)
.long
(
"admin-pin"
)
.conflicts_with_all
(
&
[
"TOTP"
,
"HOTP"
,
"USERPIN"
,
"UNLOCKPIN"
])
.conflicts_with_all
(
&
[
"TOTP"
,
"HOTP"
,
"USERPIN"
,
"UNLOCKPIN"
,
"ERASETOTP"
,
"ERASEHOTP"
])
.takes_value
(
false
)
.help
(
"Change admin pin"
))
.arg
(
Arg
::
with_name
(
"UNLOCKPIN"
)
.short
(
"l"
)
.long
(
"unlock-pin"
)
.conflicts_with_all
(
&
[
"TOTP"
,
"HOTP"
,
"USERPIN"
,
"ADMINPIN"
])
.conflicts_with_all
(
&
[
"TOTP"
,
"HOTP"
,
"USERPIN"
,
"ADMINPIN"
,
"ERASETOTP"
,
"ERASEHOTP"
])
.takes_value
(
false
)
.help
(
"Unlocks user pin after three failed login attempts"
))
.arg
(
Arg
::
with_name
(
"ERASETOTP"
)
.short
(
"e"
)
.long
(
"erase-totp"
)
.conflicts_with_all
(
&
[
"TOTP"
,
"HOTP"
,
"USERPIN"
,
"ADMINPIN"
,
"UNLOCKPIN"
,
"ERASEHOTP"
])
.takes_value
(
false
)
.help
(
"Erase totp slot"
))
.arg
(
Arg
::
with_name
(
"ERASEHOTP"
)
.short
(
"d"
)
.long
(
"erase-hotp"
)
.conflicts_with_all
(
&
[
"TOTP"
,
"HOTP"
,
"USERPIN"
,
"ADMINPIN"
,
"UNLOCKPIN"
,
"ERASETOTP"
])
.takes_value
(
false
)
.help
(
"Erase hotp slot"
))
.after_help
(
" With no argument get response if can connect to key
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment