yubico-0.11.0/.cargo_vcs_info.json0000644000000001360000000000100124050ustar { "git": { "sha1": "3e32b28f1cd4e6280609ab25dbb3a94ba3eb8272" }, "path_in_vcs": "" }yubico-0.11.0/.gitignore000064400000000000000000000000370072674642500132150ustar 00000000000000target Cargo.lock *.fmt *.iml yubico-0.11.0/.travis.yml000064400000000000000000000006240072674642500133400ustar 00000000000000language: rust cache: cargo rust: - stable allow_failures: - nightly os: - linux before_install: - if [ $TRAVIS_OS_NAME = linux ]; then sudo apt-get -qq update; else brew update; fi - if [ $TRAVIS_OS_NAME = linux ]; then sudo apt-get install -y libusb-1.0-0-dev; else brew install libusb; fi script: - cargo update --verbose - cargo build --all --all-features --verbose - cargo test --verboseyubico-0.11.0/Cargo.lock0000644000000721310000000000100103640ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "block-buffer" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" dependencies = [ "generic-array", ] [[package]] name = "bumpalo" version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" [[package]] name = "bytes" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" [[package]] name = "cc" version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "core-foundation" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" dependencies = [ "core-foundation-sys", "libc", ] [[package]] name = "core-foundation-sys" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "cpufeatures" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" dependencies = [ "libc", ] [[package]] name = "crypto-common" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" dependencies = [ "generic-array", "typenum", ] [[package]] name = "digest" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" dependencies = [ "block-buffer", "crypto-common", "subtle", ] [[package]] name = "encoding_rs" version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" dependencies = [ "cfg-if", ] [[package]] name = "fastrand" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" dependencies = [ "instant", ] [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foreign-types" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ "foreign-types-shared", ] [[package]] name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" dependencies = [ "matches", "percent-encoding", ] [[package]] name = "futures" version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" dependencies = [ "futures-channel", "futures-core", "futures-executor", "futures-io", "futures-sink", "futures-task", "futures-util", ] [[package]] name = "futures-channel" version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" dependencies = [ "futures-core", "futures-sink", ] [[package]] name = "futures-core" version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" [[package]] name = "futures-executor" version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" dependencies = [ "futures-core", "futures-task", "futures-util", ] [[package]] name = "futures-io" version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" [[package]] name = "futures-macro" version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "futures-sink" version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" [[package]] name = "futures-task" version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" [[package]] name = "futures-util" version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" dependencies = [ "futures-channel", "futures-core", "futures-io", "futures-macro", "futures-sink", "futures-task", "memchr", "pin-project-lite", "pin-utils", "slab", ] [[package]] name = "generic-array" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" dependencies = [ "typenum", "version_check", ] [[package]] name = "getrandom" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" dependencies = [ "cfg-if", "libc", "wasi 0.10.2+wasi-snapshot-preview1", ] [[package]] name = "h2" version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", "http", "indexmap", "slab", "tokio", "tokio-util", "tracing", ] [[package]] name = "hashbrown" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" [[package]] name = "hermit-abi" version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ "libc", ] [[package]] name = "hmac" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ "digest", ] [[package]] name = "http" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff8670570af52249509a86f5e3e18a08c60b177071826898fde8997cf5f6bfbb" dependencies = [ "bytes", "fnv", "itoa", ] [[package]] name = "http-body" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" dependencies = [ "bytes", "http", "pin-project-lite", ] [[package]] name = "httparse" version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" [[package]] name = "httpdate" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" version = "0.14.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", "h2", "http", "http-body", "httparse", "httpdate", "itoa", "pin-project-lite", "socket2", "tokio", "tower-service", "tracing", "want", ] [[package]] name = "hyper-tls" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", "hyper", "native-tls", "tokio", "tokio-native-tls", ] [[package]] name = "idna" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" dependencies = [ "matches", "unicode-bidi", "unicode-normalization", ] [[package]] name = "indexmap" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" dependencies = [ "autocfg", "hashbrown", ] [[package]] name = "instant" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if", ] [[package]] name = "ipnet" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" [[package]] name = "itoa" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" [[package]] name = "js-sys" version = "0.3.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" dependencies = [ "wasm-bindgen", ] [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" version = "0.2.125" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b" [[package]] name = "log" version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] [[package]] name = "matches" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "mime" version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "mio" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys", ] [[package]] name = "native-tls" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" dependencies = [ "lazy_static", "libc", "log", "openssl", "openssl-probe", "openssl-sys", "schannel", "security-framework", "security-framework-sys", "tempfile", ] [[package]] name = "num_cpus" version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ "hermit-abi", "libc", ] [[package]] name = "once_cell" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" [[package]] name = "openssl" version = "0.10.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e" dependencies = [ "bitflags", "cfg-if", "foreign-types", "libc", "once_cell", "openssl-macros", "openssl-sys", ] [[package]] name = "openssl-macros" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "openssl-probe" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" version = "0.9.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d5fd19fb3e0a8191c1e34935718976a3e70c112ab9a24af6d7cadccd9d90bc0" dependencies = [ "autocfg", "cc", "libc", "pkg-config", "vcpkg", ] [[package]] name = "percent-encoding" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "pin-project-lite" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" [[package]] name = "ppv-lite86" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "proc-macro2" version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9027b48e9d4c9175fa2218adf3557f91c1137021739951d4932f5f8268ac48aa" dependencies = [ "unicode-xid", ] [[package]] name = "quote" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" dependencies = [ "proc-macro2", ] [[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", ] [[package]] name = "rand_chacha" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", "rand_core", ] [[package]] name = "rand_core" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ "getrandom", ] [[package]] name = "redox_syscall" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" dependencies = [ "bitflags", ] [[package]] name = "remove_dir_all" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" dependencies = [ "winapi", ] [[package]] name = "reqwest" version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb" dependencies = [ "base64", "bytes", "encoding_rs", "futures-core", "futures-util", "h2", "http", "http-body", "hyper", "hyper-tls", "ipnet", "js-sys", "lazy_static", "log", "mime", "native-tls", "percent-encoding", "pin-project-lite", "serde", "serde_json", "serde_urlencoded", "tokio", "tokio-native-tls", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", "winreg", ] [[package]] name = "ryu" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" [[package]] name = "schannel" version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" dependencies = [ "lazy_static", "winapi", ] [[package]] name = "security-framework" version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" dependencies = [ "bitflags", "core-foundation", "core-foundation-sys", "libc", "security-framework-sys", ] [[package]] name = "security-framework-sys" version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" dependencies = [ "core-foundation-sys", "libc", ] [[package]] name = "serde" version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" [[package]] name = "serde_json" version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" dependencies = [ "itoa", "ryu", "serde", ] [[package]] name = "serde_urlencoded" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", "itoa", "ryu", "serde", ] [[package]] name = "sha1" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c77f4e7f65455545c2153c1253d25056825e77ee2533f0e41deb65a93a34852f" dependencies = [ "cfg-if", "cpufeatures", "digest", ] [[package]] name = "slab" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" [[package]] name = "socket2" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" dependencies = [ "libc", "winapi", ] [[package]] name = "subtle" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04066589568b72ec65f42d65a1a52436e954b168773148893c020269563decf2" dependencies = [ "proc-macro2", "quote", "unicode-xid", ] [[package]] name = "tempfile" version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ "cfg-if", "fastrand", "libc", "redox_syscall", "remove_dir_all", "winapi", ] [[package]] name = "threadpool" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" dependencies = [ "num_cpus", ] [[package]] name = "tinyvec" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] [[package]] name = "tinyvec_macros" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" version = "1.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4903bf0427cf68dddd5aa6a93220756f8be0c34fcfa9f5e6191e103e15a31395" dependencies = [ "bytes", "libc", "memchr", "mio", "num_cpus", "once_cell", "pin-project-lite", "socket2", "tokio-macros", "winapi", ] [[package]] name = "tokio-macros" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "tokio-native-tls" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" dependencies = [ "native-tls", "tokio", ] [[package]] name = "tokio-util" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", "tracing", ] [[package]] name = "tower-service" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" dependencies = [ "cfg-if", "pin-project-lite", "tracing-attributes", "tracing-core", ] [[package]] name = "tracing-attributes" version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "tracing-core" version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" dependencies = [ "lazy_static", ] [[package]] name = "try-lock" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "typenum" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "unicode-bidi" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-normalization" version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" dependencies = [ "tinyvec", ] [[package]] name = "unicode-xid" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" [[package]] name = "url" version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" dependencies = [ "form_urlencoded", "idna", "matches", "percent-encoding", ] [[package]] name = "vcpkg" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "want" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" dependencies = [ "log", "try-lock", ] [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" dependencies = [ "cfg-if", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" dependencies = [ "bumpalo", "lazy_static", "log", "proc-macro2", "quote", "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2" dependencies = [ "cfg-if", "js-sys", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" dependencies = [ "proc-macro2", "quote", "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" [[package]] name = "web-sys" version = "0.3.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" [[package]] name = "windows_i686_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" [[package]] name = "windows_i686_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" [[package]] name = "windows_x86_64_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" [[package]] name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" [[package]] name = "winreg" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ "winapi", ] [[package]] name = "yubico" version = "0.11.0" dependencies = [ "base64", "form_urlencoded", "futures", "hmac", "rand", "reqwest", "sha1", "threadpool", "tokio", ] yubico-0.11.0/Cargo.toml0000644000000030330000000000100104020ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "yubico" version = "0.11.0" authors = [ "Flavio Oliveira ", "Pierre Larger ", ] description = "Yubikey client API library" readme = "README.md" keywords = [ "yubikey", "authentication", "encryption", "OTP", "Challenge-Response", ] categories = ["authentication"] license = "MIT OR Apache-2.0" repository = "https://github.com/wisespace-io/yubico-rs" [lib] name = "yubico" path = "src/lib.rs" [dependencies.base64] version = "0.13" [dependencies.form_urlencoded] version = "1" [dependencies.futures] version = "0.3" optional = true [dependencies.hmac] version = "0.12" [dependencies.rand] version = "0.8" [dependencies.reqwest] version = "0.11" features = ["blocking"] [dependencies.sha1] version = "0.10" [dependencies.threadpool] version = "1.7" [dev-dependencies.futures] version = "0.3" [dev-dependencies.tokio] version = "1.1" features = ["macros"] [features] default = ["online-tokio"] online-tokio = ["futures"] [badges.travis-ci] repository = "wisespace-io/yubico-rs" yubico-0.11.0/Cargo.toml.orig000064400000000000000000000016060072674642500141170ustar 00000000000000[package] name = "yubico" version = "0.11.0" authors = ["Flavio Oliveira ", "Pierre Larger "] edition = "2018" description = "Yubikey client API library" license = "MIT OR Apache-2.0" keywords = ["yubikey", "authentication", "encryption", "OTP", "Challenge-Response"] categories = ["authentication"] repository = "https://github.com/wisespace-io/yubico-rs" readme = "README.md" [badges] travis-ci = { repository = "wisespace-io/yubico-rs" } [lib] name = "yubico" path = "src/lib.rs" [dependencies] base64 = "0.13" futures = { version = "0.3", optional = true } hmac = "0.12" rand = "0.8" reqwest = { version = "0.11", features = ["blocking"] } sha1 = "0.10" threadpool = "1.7" form_urlencoded = "1" [dev-dependencies] tokio = { version = "1.1", features = ["macros"] } futures = "0.3" [features] default = ["online-tokio"] online-tokio = ["futures"] yubico-0.11.0/LICENSE000064400000000000000000000003720072674642500122340ustar 00000000000000Copyright (c) 2016 Flavio Oliveira Copyright (c) 2018 Pierre-Étienne Meunier Licensed under either of * Apache License, Version 2.0, (http://www.apache.org/licenses/LICENSE-2.0) * MIT license (http://opensource.org/licenses/MIT) at your option.yubico-0.11.0/README.md000064400000000000000000000076460072674642500125210ustar 00000000000000# Yubico   [![Build Status]][travis] [![Latest Version]][crates.io] [![MIT licensed]][MIT] [![Apache-2.0 licensed]][APACHE] [Build Status]: https://travis-ci.org/wisespace-io/yubico-rs.png?branch=master [travis]: https://travis-ci.org/wisespace-io/yubico-rs [Latest Version]: https://img.shields.io/crates/v/yubico.svg [crates.io]: https://crates.io/crates/yubico [MIT licensed]: https://img.shields.io/badge/License-MIT-blue.svg [MIT]: ./LICENSE-MIT [Apache-2.0 licensed]: https://img.shields.io/badge/License-Apache%202.0-blue.svg [APACHE]: ./LICENSE-APACHE **Enables integration with the Yubico validation platform, so you can use Yubikey's one-time-password in your Rust application, allowing a user to authenticate via Yubikey.** --- ## Current features - [X] Synchronous Yubikey client API library, [validation protocol version 2.0](https://developers.yubico.com/yubikey-val/Validation_Protocol_V2.0.html). - [X] Asynchronous Yubikey client API library relying on [Tokio](https://github.com/tokio-rs/tokio) **Note:** The USB-related features have been moved to a sepatated repository, [yubico-manager](https://github.com/wisespace-io/yubico-manager) ## Usage Add this to your Cargo.toml ```toml [dependencies] yubico = "0.9" ``` The following are a list of Cargo features that can be enabled or disabled: - online-tokio (enabled by default): Provides integration to Tokio using futures. You can enable or disable them using the example below: ```toml [dependencies.yubico] version = "0.9" # don't include the default features (online-tokio) default-features = false # cherry-pick individual features features = [] ``` [Request your api key](https://upgrade.yubico.com/getapikey/). ### OTP with Default Servers ```rust extern crate yubico; use yubico::config::*; use yubico::verify; fn main() { let config = Config::default() .set_client_id("CLIENT_ID") .set_key("API_KEY"); match verify("OTP", config) { Ok(answer) => println!("{}", answer), Err(e) => println!("Error: {}", e), } } ``` ## OTP with custom API servers ```rust extern crate yubico; use yubico::verify; use yubico::config::*; fn main() { let config = Config::default() .set_client_id("CLIENT_ID") .set_key("API_KEY") .set_api_hosts(vec!["https://api.example.com/verify".into()]); match verify("OTP", config) { Ok(answer) => println!("{}", answer), Err(e) => println!("Error: {}", e), } } ``` ### Asynchronous OTP validation ```rust #![recursion_limit="128"] extern crate futures; extern crate tokio; extern crate yubico; use futures::future::Future; use yubico::verify_async; extern crate yubico; use std::io::stdin; use yubico::config::Config; fn main() { println!("Please plug in a yubikey and enter an OTP"); let client_id = std::env::var("YK_CLIENT_ID") .expect("Please set a value to the YK_CLIENT_ID environment variable."); let api_key = std::env::var("YK_API_KEY") .expect("Please set a value to the YK_API_KEY environment variable."); let otp = read_user_input(); let config = Config::default() .set_client_id(client_id) .set_key(api_key); tokio::run(verify_async(otp, config) .unwrap() .map(|_|{ println!("Valid OTP."); }) .map_err(|err|{ println!("Invalid OTP. Cause: {:?}", err); })) } fn read_user_input() -> String { let mut buf = String::new(); stdin() .read_line(&mut buf) .expect("Could not read user input."); buf } ``` ## Changelog - 0.10.0: Upgrade to `tokio` 1.1 and `reqwest` 0.11 - 0.9.2: (Yanked) Dependencies update - 0.9.1: Set HTTP Proxy (Basic-auth is optional) - 0.9.0: Moving to `tokio` 0.2 and `reqwest` 0.10 - 0.9.0-alpha.1: Moving to `futures` 0.3.0-alpha.19 - 0.8: Rename the `sync` and `async` modules to `sync_verifier` and `async_verifier` to avoid the use of the `async` reserved keyword. yubico-0.11.0/examples/README.md000064400000000000000000000005100072674642500143160ustar 00000000000000# Usage ## OTP (One Time Password) cargo run --release --example "otp" ## OTP (One Time Password) with a HTTP Proxy cargo run --release --example "otp_with_proxy" ## OTP (One Time Password) with Custom Servers cargo run --release --example "otp_custom" ## Asynchronous OTP check cargo run --release --example "otp_async"yubico-0.11.0/examples/otp.rs000064400000000000000000000004670072674642500142220ustar 00000000000000extern crate yubico; use yubico::config::*; use yubico::verify; fn main() { let config = Config::default() .set_client_id("CLIENT_ID") .set_key("API_KEY"); match verify("OTP", config) { Ok(answer) => println!("{}", answer), Err(e) => println!("Error: {}", e), } } yubico-0.11.0/examples/otp_async.rs000064400000000000000000000017160072674642500154150ustar 00000000000000extern crate futures; extern crate tokio; extern crate yubico; use yubico::verify_async; use futures::TryFutureExt; use std::io::stdin; use yubico::config::Config; #[tokio::main] async fn main() -> Result<(), ()> { println!("Please plug in a yubikey and enter an OTP"); let client_id = std::env::var("YK_CLIENT_ID") .expect("Please set a value to the YK_CLIENT_ID environment variable."); let api_key = std::env::var("YK_API_KEY") .expect("Please set a value to the YK_API_KEY environment variable."); let otp = read_user_input(); let config = Config::default().set_client_id(client_id).set_key(api_key); verify_async(otp, config) .map_ok(|()| println!("Valid OTP.")) .map_err(|err| println!("Invalid OTP. Cause: {:?}", err)) .await } fn read_user_input() -> String { let mut buf = String::new(); stdin() .read_line(&mut buf) .expect("Could not read user input."); buf } yubico-0.11.0/examples/otp_custom.rs000064400000000000000000000005750072674642500156140ustar 00000000000000extern crate yubico; use yubico::config::*; use yubico::verify; fn main() { let config = Config::default() .set_client_id("CLIENT_ID") .set_key("API_KEY") .set_api_hosts(vec!["https://api.example.com/verify".into()]); match verify("OTP", config) { Ok(answer) => println!("{}", answer), Err(e) => println!("Error: {}", e), } } yubico-0.11.0/examples/otp_with_proxy.rs000064400000000000000000000012410072674642500165050ustar 00000000000000extern crate yubico; use yubico::config::*; use yubico::verify; fn main() { println!("Please plug in a yubikey and enter an OTP"); let client_id = std::env::var("YK_CLIENT_ID") .expect("Please set a value to the YK_CLIENT_ID environment variable."); let api_key = std::env::var("YK_API_KEY") .expect("Please set a value to the YK_API_KEY environment variable."); let config = Config::default() .set_client_id(client_id) .set_key(api_key) .set_proxy_url("http://your_proxy"); match verify("OTP", config) { Ok(answer) => println!("{}", answer), Err(e) => println!("Error: {}", e), } } yubico-0.11.0/src/async_verifier.rs000064400000000000000000000057510072674642500154020ustar 00000000000000use reqwest::header::USER_AGENT; use reqwest::Client; use crate::config::Config; use crate::yubicoerror::YubicoError; use crate::{build_request, Request, Result}; use futures::stream::FuturesUnordered; use futures::StreamExt; use std::sync::Arc; pub async fn verify_async(otp: S, config: Config) -> Result<()> where S: Into, { AsyncVerifier::new(config)?.verify(otp).await } pub struct AsyncVerifier { client: Client, config: Config, } impl AsyncVerifier { pub fn new(config: Config) -> Result { let client = if config.proxy_url != "" && config.proxy_username == "" { AsyncVerifier::get_client_proxy(config.clone())? } else if config.proxy_url != "" && config.proxy_username != "" { AsyncVerifier::get_client_proxy_with_auth(config.clone())? } else { Client::builder().timeout(config.request_timeout).build()? }; Ok(AsyncVerifier { client, config }) } pub async fn verify(&self, otp: S) -> Result<()> where S: Into, { let request = Arc::new(build_request(otp, &self.config)?); // Arc because we need the future to be Send. let mut responses = FuturesUnordered::new(); self.config .api_hosts .iter() .for_each(|api_host| responses.push(self.request(request.clone(), api_host))); let mut errors = vec![]; while let Some(response) = responses.next().await { match response { Ok(()) => return Ok(()), Err(err @ YubicoError::ReplayedRequest) => errors.push(err), Err(YubicoError::HTTPStatusCode(code)) => { errors.push(YubicoError::HTTPStatusCode(code)) } Err(err) => return Err(err), } } Err(YubicoError::MultipleErrors(errors)) } async fn request(&self, request: Arc, api_host: &str) -> Result<()> { let url = request.build_url(api_host); let http_request = self .client .get(&url) .header(USER_AGENT, self.config.user_agent.clone()); let response = http_request.send().await?; let status_code = response.status(); if !status_code.is_success() { return Err(YubicoError::HTTPStatusCode(status_code)); } let text = response.text().await?; request.response_verifier.verify_response(text) } fn get_client_proxy(config: Config) -> Result { Ok(Client::builder() .timeout(config.request_timeout) .proxy(reqwest::Proxy::all(&config.proxy_url)?).build()?) } fn get_client_proxy_with_auth(config: Config) -> Result { let proxy = reqwest::Proxy::all(&config.proxy_url)? .basic_auth(&config.proxy_username, &config.proxy_password); Ok(Client::builder().timeout(config.request_timeout).proxy(proxy).build()?) } } yubico-0.11.0/src/config.rs000064400000000000000000000074010072674642500136310ustar 00000000000000use std::fmt::Display; use std::time::Duration; static API1_HOST: &str = "https://api.yubico.com/wsapi/2.0/verify"; static API2_HOST: &str = "https://api2.yubico.com/wsapi/2.0/verify"; static API3_HOST: &str = "https://api3.yubico.com/wsapi/2.0/verify"; static API4_HOST: &str = "https://api4.yubico.com/wsapi/2.0/verify"; static API5_HOST: &str = "https://api5.yubico.com/wsapi/2.0/verify"; #[derive(Clone, Debug, PartialEq)] pub enum Slot { Slot1, Slot2, } #[derive(Clone, Debug, PartialEq)] pub enum Mode { Sha1, Otp, } /// From the Validation Protocol documentation: /// /// A value 0 to 100 indicating percentage of syncing required by client, /// or strings "fast" or "secure" to use server-configured values; if /// absent, let the server decide. #[derive(Copy, Clone, Debug, PartialEq)] pub struct SyncLevel(u8); impl SyncLevel { pub fn fast() -> SyncLevel { SyncLevel(0) } pub fn secure() -> SyncLevel { SyncLevel(100) } pub fn custom(level: u8) -> SyncLevel { if level > 100 { SyncLevel(100) } else { SyncLevel(level) } } } impl Display for SyncLevel { fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { write!(f, "{}", self.0) } } #[derive(Clone, Debug, PartialEq)] pub struct Config { pub client_id: String, pub key: Vec, pub api_hosts: Vec, pub user_agent: String, pub sync_level: SyncLevel, /// The timeout for HTTP requests. pub request_timeout: Duration, pub proxy_url: String, pub proxy_username: String, pub proxy_password: String, } #[allow(dead_code)] impl Config { pub fn default() -> Config { Config { client_id: String::new(), key: Vec::new(), api_hosts: build_hosts(), user_agent: "github.com/wisespace-io/yubico-rs".to_string(), sync_level: SyncLevel::secure(), request_timeout: Duration::from_secs(30), // Value taken from the reqwest crate. proxy_url: String::new(), proxy_username: String::new(), proxy_password: String::new(), } } pub fn set_client_id(mut self, client_id: C) -> Self where C: Into, { self.client_id = client_id.into(); self } pub fn set_key(mut self, key: K) -> Self where K: Into, { self.key = key.into().into_bytes(); self } pub fn set_api_hosts(mut self, hosts: Vec) -> Self { self.api_hosts = hosts; self } pub fn set_user_agent(mut self, user_agent: String) -> Self { self.user_agent = user_agent; self } pub fn set_sync_level(mut self, level: SyncLevel) -> Self { self.sync_level = level; self } pub fn set_request_timeout(mut self, timeout: Duration) -> Self { self.request_timeout = timeout; self } pub fn set_proxy_url

(mut self, proxy_url: P) -> Self where P: Into, { self.proxy_url = proxy_url.into(); self } pub fn set_proxy_username(mut self, proxy_username: U) -> Self where U: Into, { self.proxy_username = proxy_username.into(); self } pub fn set_proxy_password

(mut self, proxy_password: P) -> Self where P: Into, { self.proxy_password = proxy_password.into(); self } } fn build_hosts() -> Vec { let mut hosts: Vec = Vec::new(); hosts.push(API1_HOST.to_string()); hosts.push(API2_HOST.to_string()); hosts.push(API3_HOST.to_string()); hosts.push(API4_HOST.to_string()); hosts.push(API5_HOST.to_string()); hosts } yubico-0.11.0/src/lib.rs000064400000000000000000000134550072674642500131400ustar 00000000000000#[cfg(feature = "online-tokio")] pub mod async_verifier; pub mod config; mod sec; pub mod sync_verifier; pub mod yubicoerror; use std::collections::BTreeMap; use base64::{decode, encode}; use config::Config; use rand::distributions::Alphanumeric; use rand::rngs::OsRng; use rand::Rng; use yubicoerror::YubicoError; #[cfg(feature = "online-tokio")] pub use async_verifier::verify_async; pub use sync_verifier::verify; type Result = ::std::result::Result; #[derive(Clone)] pub struct Request { query: String, response_verifier: ResponseVerifier, } impl Request { fn build_url(&self, for_api_host: &str) -> String { format!("{}?{}", for_api_host, self.query) } } #[derive(Clone)] pub struct ResponseVerifier { otp: String, nonce: String, key: Vec, } impl ResponseVerifier { fn verify_response(&self, raw_response: String) -> Result<()> { let response_map: BTreeMap = build_response_map(raw_response); let status: &str = &*response_map.get("status").unwrap(); if let "OK" = status { // Signature located in the response must match the signature we will build let signature_response: &str = &*response_map .get("h") .ok_or_else(|| YubicoError::InvalidResponse)?; verify_signature(signature_response, response_map.clone(), &self.key)?; // Check if "otp" in the response is the same as the "otp" supplied in the request. let otp_response: &str = &*response_map .get("otp") .ok_or_else(|| YubicoError::InvalidResponse)?; if !self.otp.eq(otp_response) { return Err(YubicoError::OTPMismatch); } // Check if "nonce" in the response is the same as the "nonce" supplied in the request. let nonce_response: &str = &*response_map .get("nonce") .ok_or_else(|| YubicoError::InvalidResponse)?; if !self.nonce.eq(nonce_response) { return Err(YubicoError::NonceMismatch); } Ok(()) } else { // Check the status of the operation match status { "BAD_OTP" => Err(YubicoError::BadOTP), "REPLAYED_OTP" => Err(YubicoError::ReplayedOTP), "BAD_SIGNATURE" => Err(YubicoError::BadSignature), "MISSING_PARAMETER" => Err(YubicoError::MissingParameter), "NO_SUCH_CLIENT" => Err(YubicoError::NoSuchClient), "OPERATION_NOT_ALLOWED" => Err(YubicoError::OperationNotAllowed), "BACKEND_ERROR" => Err(YubicoError::BackendError), "NOT_ENOUGH_ANSWERS" => Err(YubicoError::NotEnoughAnswers), "REPLAYED_REQUEST" => Err(YubicoError::ReplayedRequest), _ => Err(YubicoError::UnknownStatus), } } } } fn build_request(otp: S, config: &Config) -> Result where S: Into, { let str_otp = otp.into(); // A Yubikey can be configured to add line ending chars, or not. let str_otp = str_otp.trim().to_string(); if printable_characters(&str_otp) { let nonce: String = generate_nonce(); let mut query = form_urlencoded::Serializer::new(String::new()); query.append_pair("id", &config.client_id); query.append_pair("nonce", &nonce); query.append_pair("otp", &str_otp); query.append_pair("sl", &config.sync_level.to_string()); let query = query.finish(); match sec::build_signature(&config.key, query.as_bytes()) { Ok(signature) => { // Recover the query let mut query = form_urlencoded::Serializer::new(query); // Base 64 encode the resulting value according to RFC 4648 let encoded_signature = encode(&signature.into_bytes()); // Append the value under key h to the message. query.append_pair("h", &encoded_signature); let verifier = ResponseVerifier { otp: str_otp, nonce, key: config.key.clone(), }; let request = Request { query: query.finish(), response_verifier: verifier, }; Ok(request) } Err(error) => Err(error), } } else { Err(YubicoError::BadOTP) } } // Recommendation is that clients only check that the input consists of 32-48 printable characters fn printable_characters(otp: &str) -> bool { for c in otp.chars() { if !c.is_ascii() { return false; } } otp.len() > 32 && otp.len() < 48 } fn generate_nonce() -> String { OsRng{} .sample_iter(&Alphanumeric) .map(char::from) .take(40) .collect() } // Remove the signature itself from the values over for verification. // Sort the key/value pairs. fn verify_signature( signature_response: &str, mut response_map: BTreeMap, key: &[u8], ) -> Result<()> { response_map.remove("h"); let mut query = String::new(); for (key, value) in response_map { let param = format!("{}={}&", key, value); query.push_str(param.as_ref()); } query.pop(); // remove last & let decoded_signature = &decode(signature_response).unwrap()[..]; sec::verify_signature(key, query.as_bytes(), decoded_signature) } fn build_response_map(result: String) -> BTreeMap { let mut parameters = BTreeMap::new(); for line in result.lines() { let param: Vec<&str> = line.splitn(2, '=').collect(); if param.len() > 1 { parameters.insert(param[0].to_string(), param[1].to_string()); } } parameters } yubico-0.11.0/src/sec.rs000064400000000000000000000017350072674642500131420ustar 00000000000000use crate::yubicoerror::YubicoError; use base64::decode; use hmac::{digest::CtOutput, Hmac, Mac}; use sha1::Sha1; type HmacSha1 = Hmac; // 1. Apply the HMAC-SHA-1 algorithm on the line as an octet string using the API key as key pub fn build_signature( key: &[u8], input: &[u8], ) -> Result, YubicoError> { let decoded_key = decode(key)?; let mut hmac = match HmacSha1::new_from_slice(&decoded_key) { Ok(h) => h, Err(_) => return Err(YubicoError::InvalidKeyLength), }; hmac.update(input); Ok(hmac.finalize()) } pub fn verify_signature( key: &[u8], input: &[u8], expected: &[u8], ) -> Result<(), YubicoError> { let decoded_key = decode(key)?; let mut hmac = match HmacSha1::new_from_slice(&decoded_key) { Ok(h) => h, Err(_) => return Err(YubicoError::InvalidKeyLength), }; hmac.update(input); hmac.verify_slice(expected).map_err(|_| YubicoError::SignatureMismatch) } yubico-0.11.0/src/sync_verifier.rs000064400000000000000000000100010072674642500152210ustar 00000000000000use std::io::Read; use std::sync::mpsc::{channel, Sender}; use reqwest::header::USER_AGENT; use threadpool::ThreadPool; use crate::build_request; use crate::config::Config; use crate::yubicoerror::YubicoError; use crate::Request; use crate::Result; use reqwest::blocking::Client; use std::sync::Arc; pub fn verify(otp: S, config: Config) -> Result where S: Into, { Verifier::new(config)?.verify(otp) } pub struct Verifier { config: Config, thread_pool: ThreadPool, client: Arc, } impl Verifier { pub fn new(config: Config) -> Result { let number_of_hosts = config.api_hosts.len(); let client = if config.proxy_url != "" && config.proxy_username == "" { Verifier::get_client_proxy(config.clone())? } else if config.proxy_url != "" && config.proxy_username != "" { Verifier::get_client_proxy_with_auth(config.clone())? } else { Client::builder().timeout(config.request_timeout).build()? }; Ok(Verifier { config, thread_pool: ThreadPool::new(number_of_hosts), client: Arc::new(client), }) } pub fn verify(&self, otp: S) -> Result where S: Into, { let request = build_request(otp, &self.config)?; let number_of_hosts = self.config.api_hosts.len(); let (tx, rx) = channel(); for api_host in &self.config.api_hosts { let tx = tx.clone(); let request = request.clone(); let url = request.build_url(api_host); let user_agent = self.config.user_agent.to_string(); let client = self.client.clone(); self.thread_pool.execute(move || { process(&client, tx, url, &request, user_agent); }); } let mut success = false; let mut results: Vec> = Vec::new(); for _ in 0..number_of_hosts { match rx.recv() { Ok(Response::Signal(result)) => match result { Ok(_) => { results.truncate(0); success = true; } Err(_) => { results.push(result); } }, Err(e) => { results.push(Err(YubicoError::ChannelError(e))); break; } } } if success { Ok("The OTP is valid.".into()) } else { results.pop().ok_or_else(|| YubicoError::InvalidOtp)? } } fn get_client_proxy(config: Config) -> Result { Ok(Client::builder() .timeout(config.request_timeout) .proxy(reqwest::Proxy::all(&config.proxy_url)?).build()?) } fn get_client_proxy_with_auth(config: Config) -> Result { let proxy = reqwest::Proxy::all(&config.proxy_url)? .basic_auth(&config.proxy_username, &config.proxy_password); Ok(Client::builder().timeout(config.request_timeout).proxy(proxy).build()?) } } enum Response { Signal(Result), } fn process( client: &Client, sender: Sender, url: String, request: &Request, user_agent: String, ) { match get(client, url, user_agent) { Ok(raw_response) => { let result = request .response_verifier .verify_response(raw_response) .map(|()| "The OTP is valid.".to_owned()); sender.send(Response::Signal(result)).unwrap(); } Err(e) => { sender.send(Response::Signal(Err(e))).unwrap(); } } } pub fn get(client: &Client, url: String, user_agent: String) -> Result { let mut response = client .get(url.as_str()) .header(USER_AGENT, user_agent) .send()?; let mut data = String::new(); response.read_to_string(&mut data)?; Ok(data) } yubico-0.11.0/src/yubicoerror.rs000064400000000000000000000115120072674642500147260ustar 00000000000000use base64::DecodeError as base64Error; use std::error::Error as StdError; use std::fmt; use std::io::Error as ioError; use std::sync::mpsc::RecvError as channelError; #[derive(Debug)] pub enum YubicoError { ConfigurationError(reqwest::Error), Network(reqwest::Error), HTTPStatusCode(reqwest::StatusCode), IOError(ioError), ChannelError(channelError), DecodeError(base64Error), #[cfg(feature = "online-tokio")] MultipleErrors(Vec), BadOTP, ReplayedOTP, BadSignature, MissingParameter, NoSuchClient, OperationNotAllowed, BackendError, NotEnoughAnswers, ReplayedRequest, UnknownStatus, OTPMismatch, NonceMismatch, SignatureMismatch, InvalidKeyLength, InvalidResponse, InvalidOtp, } impl fmt::Display for YubicoError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { YubicoError::ConfigurationError(ref err) => write!(f, "Configuration error: {}", err), YubicoError::Network(ref err) => write!(f, "Connectivity error: {}", err), YubicoError::HTTPStatusCode(code) => write!(f, "Error found: {}", code), YubicoError::IOError(ref err) => write!(f, "IO error: {}", err), YubicoError::ChannelError(ref err) => write!(f, "Channel error: {}", err), YubicoError::DecodeError(ref err) => write!(f, "Decode error: {}", err), #[cfg(feature = "online-tokio")] YubicoError::MultipleErrors(ref errs) => { write!(f, "Multiple errors. ")?; for err in errs { write!(f, "{} ", err)?; } Ok(()) } YubicoError::BadOTP => write!(f, "The OTP has invalid format."), YubicoError::ReplayedOTP => write!(f, "The OTP has already been seen by the service."), YubicoError::BadSignature => write!(f, "The HMAC signature verification failed."), YubicoError::MissingParameter => write!(f, "The request lacks a parameter."), YubicoError::NoSuchClient => write!(f, "The request id does not exist."), YubicoError::OperationNotAllowed => { write!(f, "The request id is not allowed to verify OTPs.") } YubicoError::BackendError => write!( f, "Unexpected error in our server. Please contact us if you see this error." ), YubicoError::NotEnoughAnswers => write!( f, "Server could not get requested number of syncs during before timeout" ), YubicoError::ReplayedRequest => { write!(f, "Server has seen the OTP/Nonce combination before") } YubicoError::UnknownStatus => { write!(f, "Unknown status sent by the OTP validation server") } YubicoError::OTPMismatch => write!(f, "OTP mismatch, It may be an attack attempt"), YubicoError::NonceMismatch => write!(f, "Nonce mismatch, It may be an attack attempt"), YubicoError::SignatureMismatch => { write!(f, "Signature mismatch, It may be an attack attempt") } YubicoError::InvalidKeyLength => { write!(f, "Invalid key length encountered while building signature") } YubicoError::InvalidResponse => { write!(f, "Invalid response from the validation server") } YubicoError::InvalidOtp => write!(f, "Invalid OTP"), } } } impl StdError for YubicoError { fn cause(&self) -> Option<&dyn StdError> { match *self { YubicoError::Network(ref err) => Some(err), YubicoError::HTTPStatusCode(_) => None, YubicoError::IOError(ref err) => Some(err), YubicoError::ChannelError(ref err) => Some(err), YubicoError::DecodeError(ref err) => Some(err), #[cfg(feature = "online-tokio")] YubicoError::MultipleErrors(ref errs) => match errs.first() { Some(err) => Some(err), None => None, }, _ => None, } } } impl From for YubicoError { fn from(err: reqwest::Error) -> YubicoError { YubicoError::Network(err) } } impl From for YubicoError { fn from(err: reqwest::StatusCode) -> YubicoError { YubicoError::HTTPStatusCode(err) } } impl From for YubicoError { fn from(err: ioError) -> YubicoError { YubicoError::IOError(err) } } impl From for YubicoError { fn from(err: channelError) -> YubicoError { YubicoError::ChannelError(err) } } impl From for YubicoError { fn from(err: base64Error) -> YubicoError { YubicoError::DecodeError(err) } }