Skip to content

Commit

Permalink
Added TOTP support.
Browse files Browse the repository at this point in the history
  • Loading branch information
jscarle committed Aug 21, 2022
1 parent 3884c96 commit 66738d8
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 33 deletions.
72 changes: 72 additions & 0 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"

on:
push:
branches: [ "master" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "master" ]
schedule:
- cron: '33 17 * * 0'

jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write

strategy:
fail-fast: false
matrix:
language: [ 'csharp' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support

steps:
- name: Checkout repository
uses: actions/checkout@v3

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.

# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality


# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2

# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun

# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.

# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
60 changes: 32 additions & 28 deletions OnePassword.NET/OnePassword.NET.csproj
Original file line number Diff line number Diff line change
@@ -1,33 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net5.0;netstandard2.0;net45;net40;net35;net20</TargetFrameworks>
<RootNamespace>OnePassword</RootNamespace>
<AssemblyName>OnePassword.NET</AssemblyName>
<PackageId>OnePassword.NET</PackageId>
<Authors>Jean-Sebastien Carle</Authors>
<Company>Jean-Sebastien Carle</Company>
<Product>OnePassword.NET</Product>
<Description>1Password CLI Wrapper</Description>
<Version>1.0.280</Version>
<AssemblyVersion>1.0.280.0</AssemblyVersion>
<FileVersion>1.0.280.0</FileVersion>
<Copyright>Copyright © Jean-Sebastien Carle 2021</Copyright>
<RepositoryUrl>https://github.com/jscarle/OnePassword.NET</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>1Password OnePassword</PackageTags>
<PackageLicenseFile>LICENSE.md</PackageLicenseFile>
</PropertyGroup>
<PropertyGroup>
<TargetFrameworks>net5.0;netstandard2.0;net45;net40;net35;net20</TargetFrameworks>
<RootNamespace>OnePassword</RootNamespace>
<AssemblyName>OnePassword.NET</AssemblyName>
<PackageId>OnePassword.NET</PackageId>
<Authors>Jean-Sebastien Carle</Authors>
<Company>Jean-Sebastien Carle</Company>
<Product>OnePassword.NET</Product>
<Description>1Password CLI Wrapper</Description>
<Version>1.1.1</Version>
<AssemblyVersion>1.1.1.0</AssemblyVersion>
<FileVersion>1.1.1.0</FileVersion>
<Copyright>Copyright © Jean-Sebastien Carle 2021-2022</Copyright>
<RepositoryUrl>https://github.com/jscarle/OnePassword.NET</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>1Password OnePassword</PackageTags>
<PackageLicenseFile>LICENSE.md</PackageLicenseFile>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="11.0.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
<Reference Include="System.IO.Compression" />
</ItemGroup>

<ItemGroup>
<None Include="..\LICENSE.md">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
</ItemGroup>

<ItemGroup>
<None Include="..\LICENSE.md">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
</ItemGroup>

</Project>
37 changes: 32 additions & 5 deletions OnePassword.NET/OnePasswordManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.IO.Compression;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using Newtonsoft.Json;
using OnePassword.Documents;
using OnePassword.Groups;
Expand All @@ -17,6 +18,7 @@ namespace OnePassword
{
public class OnePasswordManager
{
private readonly TimeSpan _totpProcessStartupTimeout = TimeSpan.FromMilliseconds(1000);
private readonly string _opPath;
private readonly bool _verbose;
private string _shorthand;
Expand Down Expand Up @@ -223,7 +225,7 @@ public Template GetTemplate(Template template)
{
template.Details = JsonConvert.DeserializeObject<ItemDetails>(Op($"get template \"{template.Name}\""));
return template;
}
}

public User GetUser(User user) => JsonConvert.DeserializeObject<User>(Op($"get user \"{user.Uuid}\""));

Expand Down Expand Up @@ -308,19 +310,29 @@ public ItemList ListItems(Vault vault, Template template, string tag, bool inclu
public void RemoveUser(User user, Group group) => Op($"remove user \"{user.Uuid}\" \"{group.Uuid}\"");

public void SignIn(string domain, string email, string secretKey, string password, string shorthand = "")
{
SignIn(domain, email, secretKey, password, "", shorthand);
}

public void SignInTotp(string domain, string email, string secretKey, string password, string totp, string shorthand = "")
{
SignIn(domain, email, secretKey, password, totp, shorthand);
}

private void SignIn(string domain, string email, string secretKey, string password, string totp, string shorthand)
{
Regex opDeviceRegex = new Regex("OP_DEVICE=(?<UUID>[a-z0-9]+)");

string command = $"signin {domain} {email} {secretKey} --raw";
if (!string.IsNullOrEmpty(shorthand))
command += $" --shorthand {shorthand}";

string result = Op(command, password, true);
string result = Op(command, new string[] { password, totp }, true);
if (result.Contains("No saved device ID."))
{
string deviceUuid = opDeviceRegex.Match(result).Groups["UUID"].Value;
Environment.SetEnvironmentVariable("OP_DEVICE", deviceUuid);
result = Op(command, password);
result = Op(command, new string[] { password, totp });
}

if (result.StartsWith("[ERROR]"))
Expand Down Expand Up @@ -399,6 +411,12 @@ private static string GetStandardOutput(Process process)

private string Op(string command, string input = "", bool returnError = false)
{
return Op(command, new string[] { input });
}

private string Op(string command, string[] input, bool returnError = false)
{

string arguments = command;
if (!string.IsNullOrEmpty(_sessionId))
arguments += $" --session {_sessionId}";
Expand All @@ -423,8 +441,17 @@ private string Op(string command, string input = "", bool returnError = false)
if (process is null)
throw new Exception($"Could not start process for {_opPath}.");

if (input.Length > 0)
process.StandardInput.WriteLine(input);
if (input != null && input.Length > 0)
{
if (input.Length > 1)
Thread.Sleep(_totpProcessStartupTimeout);

foreach (var inputLine in input)
{
process.StandardInput.WriteLine(inputLine);
process.StandardInput.Flush();
}
}

string output = GetStandardOutput(process);
if (_verbose)
Expand Down

0 comments on commit 66738d8

Please sign in to comment.