kanidm/docs/v1.0.0rc2/rustdoc/src/kanidm_cli/session.rs.html
2022-10-17 10:25:41 +00:00

1048 lines
68 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Source of the Rust file `kanidm_tools/src/cli/session.rs`."><meta name="keywords" content="rust, rustlang, rust-lang"><title>session.rs - source</title><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceSerif4-Regular.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../FiraSans-Regular.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../FiraSans-Medium.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceCodePro-Regular.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceSerif4-Bold.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceCodePro-Semibold.ttf.woff2"><link rel="stylesheet" type="text/css" href="../../normalize.css"><link rel="stylesheet" type="text/css" href="../../rustdoc.css" id="mainThemeStyle"><link rel="stylesheet" type="text/css" href="../../ayu.css" disabled><link rel="stylesheet" type="text/css" href="../../dark.css" disabled><link rel="stylesheet" type="text/css" href="../../light.css" id="themeStyle"><script id="default-settings" ></script><script src="../../storage.js"></script><script defer src="../../source-script.js"></script><script defer src="../../source-files.js"></script><script defer src="../../main.js"></script><noscript><link rel="stylesheet" href="../../noscript.css"></noscript><link rel="alternate icon" type="image/png" href="../../favicon-16x16.png"><link rel="alternate icon" type="image/png" href="../../favicon-32x32.png"><link rel="icon" type="image/svg+xml" href="../../favicon.svg"></head><body class="rustdoc source"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle">&#9776;</button><a class="sidebar-logo" href="../../kanidm_cli/index.html"><div class="logo-container"><img class="rust-logo" src="../../rust-logo.svg" alt="logo"></div></a><h2 class="location"></h2></nav><nav class="sidebar"><a class="sidebar-logo" href="../../kanidm_cli/index.html"><div class="logo-container"><img class="rust-logo" src="../../rust-logo.svg" alt="logo"></div></a></nav><main><div class="width-limiter"><div class="sub-container"><a class="sub-logo-container" href="../../kanidm_cli/index.html"><img class="rust-logo" src="../../rust-logo.svg" alt="logo"></a><nav class="sub"><form class="search-form"><div class="search-container"><span></span><input class="search-input" name="search" autocomplete="off" spellcheck="false" placeholder="Click or press S to search, ? for more options…" type="search"><div id="help-button" title="help" tabindex="-1"><button type="button">?</button></div><div id="settings-menu" tabindex="-1"><a href="../../settings.html" title="settings"><img width="22" height="22" alt="Change settings" src="../../wheel.svg"></a></div></div></form></nav></div><section id="main-content" class="content"><div class="example-wrap"><pre class="line-numbers"><span id="1">1</span>
<span id="2">2</span>
<span id="3">3</span>
<span id="4">4</span>
<span id="5">5</span>
<span id="6">6</span>
<span id="7">7</span>
<span id="8">8</span>
<span id="9">9</span>
<span id="10">10</span>
<span id="11">11</span>
<span id="12">12</span>
<span id="13">13</span>
<span id="14">14</span>
<span id="15">15</span>
<span id="16">16</span>
<span id="17">17</span>
<span id="18">18</span>
<span id="19">19</span>
<span id="20">20</span>
<span id="21">21</span>
<span id="22">22</span>
<span id="23">23</span>
<span id="24">24</span>
<span id="25">25</span>
<span id="26">26</span>
<span id="27">27</span>
<span id="28">28</span>
<span id="29">29</span>
<span id="30">30</span>
<span id="31">31</span>
<span id="32">32</span>
<span id="33">33</span>
<span id="34">34</span>
<span id="35">35</span>
<span id="36">36</span>
<span id="37">37</span>
<span id="38">38</span>
<span id="39">39</span>
<span id="40">40</span>
<span id="41">41</span>
<span id="42">42</span>
<span id="43">43</span>
<span id="44">44</span>
<span id="45">45</span>
<span id="46">46</span>
<span id="47">47</span>
<span id="48">48</span>
<span id="49">49</span>
<span id="50">50</span>
<span id="51">51</span>
<span id="52">52</span>
<span id="53">53</span>
<span id="54">54</span>
<span id="55">55</span>
<span id="56">56</span>
<span id="57">57</span>
<span id="58">58</span>
<span id="59">59</span>
<span id="60">60</span>
<span id="61">61</span>
<span id="62">62</span>
<span id="63">63</span>
<span id="64">64</span>
<span id="65">65</span>
<span id="66">66</span>
<span id="67">67</span>
<span id="68">68</span>
<span id="69">69</span>
<span id="70">70</span>
<span id="71">71</span>
<span id="72">72</span>
<span id="73">73</span>
<span id="74">74</span>
<span id="75">75</span>
<span id="76">76</span>
<span id="77">77</span>
<span id="78">78</span>
<span id="79">79</span>
<span id="80">80</span>
<span id="81">81</span>
<span id="82">82</span>
<span id="83">83</span>
<span id="84">84</span>
<span id="85">85</span>
<span id="86">86</span>
<span id="87">87</span>
<span id="88">88</span>
<span id="89">89</span>
<span id="90">90</span>
<span id="91">91</span>
<span id="92">92</span>
<span id="93">93</span>
<span id="94">94</span>
<span id="95">95</span>
<span id="96">96</span>
<span id="97">97</span>
<span id="98">98</span>
<span id="99">99</span>
<span id="100">100</span>
<span id="101">101</span>
<span id="102">102</span>
<span id="103">103</span>
<span id="104">104</span>
<span id="105">105</span>
<span id="106">106</span>
<span id="107">107</span>
<span id="108">108</span>
<span id="109">109</span>
<span id="110">110</span>
<span id="111">111</span>
<span id="112">112</span>
<span id="113">113</span>
<span id="114">114</span>
<span id="115">115</span>
<span id="116">116</span>
<span id="117">117</span>
<span id="118">118</span>
<span id="119">119</span>
<span id="120">120</span>
<span id="121">121</span>
<span id="122">122</span>
<span id="123">123</span>
<span id="124">124</span>
<span id="125">125</span>
<span id="126">126</span>
<span id="127">127</span>
<span id="128">128</span>
<span id="129">129</span>
<span id="130">130</span>
<span id="131">131</span>
<span id="132">132</span>
<span id="133">133</span>
<span id="134">134</span>
<span id="135">135</span>
<span id="136">136</span>
<span id="137">137</span>
<span id="138">138</span>
<span id="139">139</span>
<span id="140">140</span>
<span id="141">141</span>
<span id="142">142</span>
<span id="143">143</span>
<span id="144">144</span>
<span id="145">145</span>
<span id="146">146</span>
<span id="147">147</span>
<span id="148">148</span>
<span id="149">149</span>
<span id="150">150</span>
<span id="151">151</span>
<span id="152">152</span>
<span id="153">153</span>
<span id="154">154</span>
<span id="155">155</span>
<span id="156">156</span>
<span id="157">157</span>
<span id="158">158</span>
<span id="159">159</span>
<span id="160">160</span>
<span id="161">161</span>
<span id="162">162</span>
<span id="163">163</span>
<span id="164">164</span>
<span id="165">165</span>
<span id="166">166</span>
<span id="167">167</span>
<span id="168">168</span>
<span id="169">169</span>
<span id="170">170</span>
<span id="171">171</span>
<span id="172">172</span>
<span id="173">173</span>
<span id="174">174</span>
<span id="175">175</span>
<span id="176">176</span>
<span id="177">177</span>
<span id="178">178</span>
<span id="179">179</span>
<span id="180">180</span>
<span id="181">181</span>
<span id="182">182</span>
<span id="183">183</span>
<span id="184">184</span>
<span id="185">185</span>
<span id="186">186</span>
<span id="187">187</span>
<span id="188">188</span>
<span id="189">189</span>
<span id="190">190</span>
<span id="191">191</span>
<span id="192">192</span>
<span id="193">193</span>
<span id="194">194</span>
<span id="195">195</span>
<span id="196">196</span>
<span id="197">197</span>
<span id="198">198</span>
<span id="199">199</span>
<span id="200">200</span>
<span id="201">201</span>
<span id="202">202</span>
<span id="203">203</span>
<span id="204">204</span>
<span id="205">205</span>
<span id="206">206</span>
<span id="207">207</span>
<span id="208">208</span>
<span id="209">209</span>
<span id="210">210</span>
<span id="211">211</span>
<span id="212">212</span>
<span id="213">213</span>
<span id="214">214</span>
<span id="215">215</span>
<span id="216">216</span>
<span id="217">217</span>
<span id="218">218</span>
<span id="219">219</span>
<span id="220">220</span>
<span id="221">221</span>
<span id="222">222</span>
<span id="223">223</span>
<span id="224">224</span>
<span id="225">225</span>
<span id="226">226</span>
<span id="227">227</span>
<span id="228">228</span>
<span id="229">229</span>
<span id="230">230</span>
<span id="231">231</span>
<span id="232">232</span>
<span id="233">233</span>
<span id="234">234</span>
<span id="235">235</span>
<span id="236">236</span>
<span id="237">237</span>
<span id="238">238</span>
<span id="239">239</span>
<span id="240">240</span>
<span id="241">241</span>
<span id="242">242</span>
<span id="243">243</span>
<span id="244">244</span>
<span id="245">245</span>
<span id="246">246</span>
<span id="247">247</span>
<span id="248">248</span>
<span id="249">249</span>
<span id="250">250</span>
<span id="251">251</span>
<span id="252">252</span>
<span id="253">253</span>
<span id="254">254</span>
<span id="255">255</span>
<span id="256">256</span>
<span id="257">257</span>
<span id="258">258</span>
<span id="259">259</span>
<span id="260">260</span>
<span id="261">261</span>
<span id="262">262</span>
<span id="263">263</span>
<span id="264">264</span>
<span id="265">265</span>
<span id="266">266</span>
<span id="267">267</span>
<span id="268">268</span>
<span id="269">269</span>
<span id="270">270</span>
<span id="271">271</span>
<span id="272">272</span>
<span id="273">273</span>
<span id="274">274</span>
<span id="275">275</span>
<span id="276">276</span>
<span id="277">277</span>
<span id="278">278</span>
<span id="279">279</span>
<span id="280">280</span>
<span id="281">281</span>
<span id="282">282</span>
<span id="283">283</span>
<span id="284">284</span>
<span id="285">285</span>
<span id="286">286</span>
<span id="287">287</span>
<span id="288">288</span>
<span id="289">289</span>
<span id="290">290</span>
<span id="291">291</span>
<span id="292">292</span>
<span id="293">293</span>
<span id="294">294</span>
<span id="295">295</span>
<span id="296">296</span>
<span id="297">297</span>
<span id="298">298</span>
<span id="299">299</span>
<span id="300">300</span>
<span id="301">301</span>
<span id="302">302</span>
<span id="303">303</span>
<span id="304">304</span>
<span id="305">305</span>
<span id="306">306</span>
<span id="307">307</span>
<span id="308">308</span>
<span id="309">309</span>
<span id="310">310</span>
<span id="311">311</span>
<span id="312">312</span>
<span id="313">313</span>
<span id="314">314</span>
<span id="315">315</span>
<span id="316">316</span>
<span id="317">317</span>
<span id="318">318</span>
<span id="319">319</span>
<span id="320">320</span>
<span id="321">321</span>
<span id="322">322</span>
<span id="323">323</span>
<span id="324">324</span>
<span id="325">325</span>
<span id="326">326</span>
<span id="327">327</span>
<span id="328">328</span>
<span id="329">329</span>
<span id="330">330</span>
<span id="331">331</span>
<span id="332">332</span>
<span id="333">333</span>
<span id="334">334</span>
<span id="335">335</span>
<span id="336">336</span>
<span id="337">337</span>
<span id="338">338</span>
<span id="339">339</span>
<span id="340">340</span>
<span id="341">341</span>
<span id="342">342</span>
<span id="343">343</span>
<span id="344">344</span>
<span id="345">345</span>
<span id="346">346</span>
<span id="347">347</span>
<span id="348">348</span>
<span id="349">349</span>
<span id="350">350</span>
<span id="351">351</span>
<span id="352">352</span>
<span id="353">353</span>
<span id="354">354</span>
<span id="355">355</span>
<span id="356">356</span>
<span id="357">357</span>
<span id="358">358</span>
<span id="359">359</span>
<span id="360">360</span>
<span id="361">361</span>
<span id="362">362</span>
<span id="363">363</span>
<span id="364">364</span>
<span id="365">365</span>
<span id="366">366</span>
<span id="367">367</span>
<span id="368">368</span>
<span id="369">369</span>
<span id="370">370</span>
<span id="371">371</span>
<span id="372">372</span>
<span id="373">373</span>
<span id="374">374</span>
<span id="375">375</span>
<span id="376">376</span>
<span id="377">377</span>
<span id="378">378</span>
<span id="379">379</span>
<span id="380">380</span>
<span id="381">381</span>
<span id="382">382</span>
<span id="383">383</span>
<span id="384">384</span>
<span id="385">385</span>
<span id="386">386</span>
<span id="387">387</span>
<span id="388">388</span>
<span id="389">389</span>
<span id="390">390</span>
<span id="391">391</span>
<span id="392">392</span>
<span id="393">393</span>
<span id="394">394</span>
<span id="395">395</span>
<span id="396">396</span>
<span id="397">397</span>
<span id="398">398</span>
<span id="399">399</span>
<span id="400">400</span>
<span id="401">401</span>
<span id="402">402</span>
<span id="403">403</span>
<span id="404">404</span>
<span id="405">405</span>
<span id="406">406</span>
<span id="407">407</span>
<span id="408">408</span>
<span id="409">409</span>
<span id="410">410</span>
<span id="411">411</span>
<span id="412">412</span>
<span id="413">413</span>
<span id="414">414</span>
<span id="415">415</span>
<span id="416">416</span>
<span id="417">417</span>
<span id="418">418</span>
<span id="419">419</span>
<span id="420">420</span>
<span id="421">421</span>
<span id="422">422</span>
<span id="423">423</span>
<span id="424">424</span>
<span id="425">425</span>
<span id="426">426</span>
<span id="427">427</span>
<span id="428">428</span>
<span id="429">429</span>
<span id="430">430</span>
<span id="431">431</span>
<span id="432">432</span>
<span id="433">433</span>
<span id="434">434</span>
<span id="435">435</span>
<span id="436">436</span>
<span id="437">437</span>
<span id="438">438</span>
<span id="439">439</span>
<span id="440">440</span>
<span id="441">441</span>
<span id="442">442</span>
<span id="443">443</span>
<span id="444">444</span>
<span id="445">445</span>
<span id="446">446</span>
<span id="447">447</span>
<span id="448">448</span>
<span id="449">449</span>
<span id="450">450</span>
<span id="451">451</span>
<span id="452">452</span>
<span id="453">453</span>
<span id="454">454</span>
<span id="455">455</span>
<span id="456">456</span>
<span id="457">457</span>
<span id="458">458</span>
<span id="459">459</span>
<span id="460">460</span>
<span id="461">461</span>
<span id="462">462</span>
<span id="463">463</span>
<span id="464">464</span>
<span id="465">465</span>
<span id="466">466</span>
<span id="467">467</span>
<span id="468">468</span>
<span id="469">469</span>
<span id="470">470</span>
<span id="471">471</span>
<span id="472">472</span>
<span id="473">473</span>
<span id="474">474</span>
<span id="475">475</span>
<span id="476">476</span>
<span id="477">477</span>
<span id="478">478</span>
<span id="479">479</span>
<span id="480">480</span>
<span id="481">481</span>
<span id="482">482</span>
<span id="483">483</span>
<span id="484">484</span>
<span id="485">485</span>
<span id="486">486</span>
<span id="487">487</span>
<span id="488">488</span>
<span id="489">489</span>
<span id="490">490</span>
<span id="491">491</span>
<span id="492">492</span>
<span id="493">493</span>
<span id="494">494</span>
<span id="495">495</span>
<span id="496">496</span>
<span id="497">497</span>
<span id="498">498</span>
<span id="499">499</span>
<span id="500">500</span>
<span id="501">501</span>
<span id="502">502</span>
<span id="503">503</span>
<span id="504">504</span>
<span id="505">505</span>
<span id="506">506</span>
<span id="507">507</span>
<span id="508">508</span>
<span id="509">509</span>
<span id="510">510</span>
<span id="511">511</span>
<span id="512">512</span>
<span id="513">513</span>
<span id="514">514</span>
<span id="515">515</span>
<span id="516">516</span>
<span id="517">517</span>
<span id="518">518</span>
<span id="519">519</span>
<span id="520">520</span>
<span id="521">521</span>
<span id="522">522</span>
<span id="523">523</span>
</pre><pre class="rust"><code><span class="kw">use</span> <span class="ident">std::collections::BTreeMap</span>;
<span class="kw">use</span> <span class="ident">std::fs</span>::{<span class="ident">create_dir</span>, <span class="ident">File</span>};
<span class="kw">use</span> <span class="ident">std::io</span>::{<span class="self">self</span>, <span class="ident">BufReader</span>, <span class="ident">BufWriter</span>, <span class="ident">ErrorKind</span>, <span class="ident">Write</span>};
<span class="kw">use</span> <span class="ident">std::path::PathBuf</span>;
<span class="kw">use</span> <span class="ident">std::str::FromStr</span>;
<span class="kw">use</span> <span class="ident">compact_jwt::JwsUnverified</span>;
<span class="kw">use</span> <span class="ident">dialoguer::theme::ColorfulTheme</span>;
<span class="kw">use</span> <span class="ident">dialoguer::Select</span>;
<span class="kw">use</span> <span class="ident">kanidm_client</span>::{<span class="ident">ClientError</span>, <span class="ident">KanidmClient</span>};
<span class="kw">use</span> <span class="ident">kanidm_proto::v1</span>::{<span class="ident">AuthAllowed</span>, <span class="ident">AuthResponse</span>, <span class="ident">AuthState</span>, <span class="ident">UserAuthToken</span>};
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">target_family</span> <span class="op">=</span> <span class="string">&quot;unix&quot;</span>)]</span>
<span class="kw">use</span> <span class="ident">libc::umask</span>;
<span class="kw">use</span> <span class="ident">webauthn_authenticator_rs::prelude::RequestChallengeResponse</span>;
<span class="kw">use</span> <span class="ident">webauthn_authenticator_rs::u2fhid::U2FHid</span>;
<span class="kw">use</span> <span class="ident">webauthn_authenticator_rs::WebauthnAuthenticator</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::common::prompt_for_username_get_username</span>;
<span class="kw">use</span> <span class="kw">crate</span>::{<span class="ident">LoginOpt</span>, <span class="ident">LogoutOpt</span>, <span class="ident">SessionOpt</span>};
<span class="kw">static</span> <span class="ident">TOKEN_DIR</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;~/.cache&quot;</span>;
<span class="kw">static</span> <span class="ident">TOKEN_PATH</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;~/.cache/kanidm_tokens&quot;</span>;
<span class="attribute">#[<span class="ident">allow</span>(<span class="ident">clippy::result_unit_err</span>)]</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">read_tokens</span>() -&gt; <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">BTreeMap</span><span class="op">&lt;</span><span class="ident">String</span>, <span class="ident">String</span><span class="op">&gt;</span>, ()<span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">token_path</span> <span class="op">=</span> <span class="ident">PathBuf::from</span>(<span class="ident">shellexpand::tilde</span>(<span class="ident">TOKEN_PATH</span>).<span class="ident">into_owned</span>());
<span class="kw">if</span> <span class="op">!</span><span class="ident">token_path</span>.<span class="ident">exists</span>() {
<span class="macro">debug!</span>(
<span class="string">&quot;Token cache file path {:?} does not exist, returning an empty token store.&quot;</span>,
<span class="ident">TOKEN_PATH</span>
);
<span class="kw">return</span> <span class="prelude-val">Ok</span>(<span class="ident">BTreeMap::new</span>());
}
<span class="macro">debug!</span>(<span class="string">&quot;Attempting to read tokens from {:?}&quot;</span>, <span class="kw-2">&amp;</span><span class="ident">token_path</span>);
<span class="comment">// If the file does not exist, return Ok&lt;map&gt;</span>
<span class="kw">let</span> <span class="ident">file</span> <span class="op">=</span> <span class="kw">match</span> <span class="ident">File::open</span>(<span class="kw-2">&amp;</span><span class="ident">token_path</span>) {
<span class="prelude-val">Ok</span>(<span class="ident">f</span>) =&gt; <span class="ident">f</span>,
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; {
<span class="kw">match</span> <span class="ident">e</span>.<span class="ident">kind</span>() {
<span class="ident">ErrorKind::PermissionDenied</span> =&gt; {
<span class="comment">// we bail here because you won&#39;t be able to write them back...</span>
<span class="macro">error!</span>(
<span class="string">&quot;Permission denied reading token store file {:?}&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">token_path</span>
);
<span class="kw">return</span> <span class="prelude-val">Err</span>(());
}
<span class="comment">// other errors are OK to continue past</span>
<span class="kw">_</span> =&gt; {
<span class="macro">warn!</span>(
<span class="string">&quot;Cannot read tokens from {} due to error: {:?} ... continuing.&quot;</span>,
<span class="ident">TOKEN_PATH</span>, <span class="ident">e</span>
);
<span class="kw">return</span> <span class="prelude-val">Ok</span>(<span class="ident">BTreeMap::new</span>());
}
};
}
};
<span class="kw">let</span> <span class="ident">reader</span> <span class="op">=</span> <span class="ident">BufReader::new</span>(<span class="ident">file</span>);
<span class="comment">// Else try to read</span>
<span class="ident">serde_json::from_reader</span>(<span class="ident">reader</span>).<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> {
<span class="macro">error!</span>(
<span class="string">&quot;JSON/IO error reading tokens from {:?} -&gt; {:?}&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">token_path</span>, <span class="ident">e</span>
);
})
}
<span class="attribute">#[<span class="ident">allow</span>(<span class="ident">clippy::result_unit_err</span>)]</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">write_tokens</span>(<span class="ident">tokens</span>: <span class="kw-2">&amp;</span><span class="ident">BTreeMap</span><span class="op">&lt;</span><span class="ident">String</span>, <span class="ident">String</span><span class="op">&gt;</span>) -&gt; <span class="prelude-ty">Result</span><span class="op">&lt;</span>(), ()<span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">token_dir</span> <span class="op">=</span> <span class="ident">PathBuf::from</span>(<span class="ident">shellexpand::tilde</span>(<span class="ident">TOKEN_DIR</span>).<span class="ident">into_owned</span>());
<span class="kw">let</span> <span class="ident">token_path</span> <span class="op">=</span> <span class="ident">PathBuf::from</span>(<span class="ident">shellexpand::tilde</span>(<span class="ident">TOKEN_PATH</span>).<span class="ident">into_owned</span>());
<span class="ident">token_dir</span>
.<span class="ident">parent</span>()
.<span class="ident">ok_or_else</span>(<span class="op">|</span><span class="op">|</span> {
<span class="macro">error!</span>(
<span class="string">&quot;Parent directory to {} is invalid (root directory?).&quot;</span>,
<span class="ident">TOKEN_DIR</span>
);
})
.<span class="ident">and_then</span>(<span class="op">|</span><span class="ident">parent_dir</span><span class="op">|</span> {
<span class="kw">if</span> <span class="ident">parent_dir</span>.<span class="ident">exists</span>() {
<span class="prelude-val">Ok</span>(())
} <span class="kw">else</span> {
<span class="macro">error!</span>(<span class="string">&quot;Parent directory to {} does not exist.&quot;</span>, <span class="ident">TOKEN_DIR</span>);
<span class="prelude-val">Err</span>(())
}
})<span class="question-mark">?</span>;
<span class="kw">if</span> <span class="op">!</span><span class="ident">token_dir</span>.<span class="ident">exists</span>() {
<span class="ident">create_dir</span>(<span class="ident">token_dir</span>).<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> {
<span class="macro">error!</span>(<span class="string">&quot;Unable to create directory - {} {:?}&quot;</span>, <span class="ident">TOKEN_DIR</span>, <span class="ident">e</span>);
})<span class="question-mark">?</span>;
}
<span class="comment">// Take away group/everyone read/write</span>
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">target_family</span> <span class="op">=</span> <span class="string">&quot;unix&quot;</span>)]</span>
<span class="kw">let</span> <span class="ident">before</span> <span class="op">=</span> <span class="kw">unsafe</span> { <span class="ident">umask</span>(<span class="number">0o177</span>) };
<span class="kw">let</span> <span class="ident">file</span> <span class="op">=</span> <span class="ident">File::create</span>(<span class="kw-2">&amp;</span><span class="ident">token_path</span>).<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> {
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">target_family</span> <span class="op">=</span> <span class="string">&quot;unix&quot;</span>)]</span>
<span class="kw">let</span> <span class="kw">_</span> <span class="op">=</span> <span class="kw">unsafe</span> { <span class="ident">umask</span>(<span class="ident">before</span>) };
<span class="macro">error!</span>(<span class="string">&quot;Can not write to {} -&gt; {:?}&quot;</span>, <span class="ident">TOKEN_PATH</span>, <span class="ident">e</span>);
})<span class="question-mark">?</span>;
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">target_family</span> <span class="op">=</span> <span class="string">&quot;unix&quot;</span>)]</span>
<span class="kw">let</span> <span class="kw">_</span> <span class="op">=</span> <span class="kw">unsafe</span> { <span class="ident">umask</span>(<span class="ident">before</span>) };
<span class="kw">let</span> <span class="ident">writer</span> <span class="op">=</span> <span class="ident">BufWriter::new</span>(<span class="ident">file</span>);
<span class="ident">serde_json::to_writer_pretty</span>(<span class="ident">writer</span>, <span class="ident">tokens</span>).<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> {
<span class="macro">error!</span>(
<span class="string">&quot;JSON/IO error writing tokens to file {:?} -&gt; {:?}&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">token_path</span>, <span class="ident">e</span>
);
})
}
<span class="doccomment">/// An interactive dialog to choose from given options</span>
<span class="kw">fn</span> <span class="ident">get_index_choice_dialoguer</span>(<span class="ident">msg</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>, <span class="ident">options</span>: <span class="kw-2">&amp;</span>[<span class="ident">String</span>]) -&gt; <span class="ident">usize</span> {
<span class="kw">let</span> <span class="ident">user_select</span> <span class="op">=</span> <span class="ident">Select::with_theme</span>(<span class="kw-2">&amp;</span><span class="ident">ColorfulTheme::default</span>())
.<span class="ident">with_prompt</span>(<span class="ident">msg</span>)
.<span class="ident">default</span>(<span class="number">0</span>)
.<span class="ident">items</span>(<span class="ident">options</span>)
.<span class="ident">interact</span>();
<span class="kw">let</span> <span class="ident">selection</span> <span class="op">=</span> <span class="kw">match</span> <span class="ident">user_select</span> {
<span class="prelude-val">Err</span>(<span class="ident">error</span>) =&gt; {
<span class="macro">error!</span>(<span class="string">&quot;Failed to handle user input: {:?}&quot;</span>, <span class="ident">error</span>);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
}
<span class="prelude-val">Ok</span>(<span class="ident">value</span>) =&gt; <span class="ident">value</span>,
};
<span class="macro">debug!</span>(<span class="string">&quot;Index of the chosen menu item: {:?}&quot;</span>, <span class="ident">selection</span>);
<span class="ident">selection</span>
}
<span class="kw">impl</span> <span class="ident">LoginOpt</span> {
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">debug</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="ident">bool</span> {
<span class="self">self</span>.<span class="ident">copt</span>.<span class="ident">debug</span>
}
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">do_password</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">client</span>: <span class="kw-2">&amp;mut</span> <span class="ident">KanidmClient</span>) -&gt; <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">AuthResponse</span>, <span class="ident">ClientError</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">password</span> <span class="op">=</span> <span class="ident">rpassword::prompt_password</span>(<span class="string">&quot;Enter password: &quot;</span>).<span class="ident">unwrap_or_else</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> {
<span class="macro">error!</span>(<span class="string">&quot;Failed to create password prompt -- {:?}&quot;</span>, <span class="ident">e</span>);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
});
<span class="ident">client</span>.<span class="ident">auth_step_password</span>(<span class="ident">password</span>.<span class="ident">as_str</span>()).<span class="kw">await</span>
}
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">do_backup_code</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">client</span>: <span class="kw-2">&amp;mut</span> <span class="ident">KanidmClient</span>) -&gt; <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">AuthResponse</span>, <span class="ident">ClientError</span><span class="op">&gt;</span> {
<span class="macro">print!</span>(<span class="string">&quot;Enter Backup Code: &quot;</span>);
<span class="comment">// We flush stdout so it&#39;ll write the buffer to screen, continuing operation. Without it, the application halts.</span>
<span class="attribute">#[<span class="ident">allow</span>(<span class="ident">clippy::unwrap_used</span>)]</span>
<span class="ident">io::stdout</span>().<span class="ident">flush</span>().<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">backup_code</span> <span class="op">=</span> <span class="ident">String::new</span>();
<span class="kw">loop</span> {
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Err</span>(<span class="ident">e</span>) <span class="op">=</span> <span class="ident">io::stdin</span>().<span class="ident">read_line</span>(<span class="kw-2">&amp;mut</span> <span class="ident">backup_code</span>) {
<span class="macro">error!</span>(<span class="string">&quot;Failed to read from stdin -&gt; {:?}&quot;</span>, <span class="ident">e</span>);
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">ClientError::SystemError</span>);
};
<span class="kw">if</span> <span class="op">!</span><span class="ident">backup_code</span>.<span class="ident">trim</span>().<span class="ident">is_empty</span>() {
<span class="kw">break</span>;
};
}
<span class="ident">client</span>.<span class="ident">auth_step_backup_code</span>(<span class="ident">backup_code</span>.<span class="ident">trim</span>()).<span class="kw">await</span>
}
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">do_totp</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">client</span>: <span class="kw-2">&amp;mut</span> <span class="ident">KanidmClient</span>) -&gt; <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">AuthResponse</span>, <span class="ident">ClientError</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">totp</span> <span class="op">=</span> <span class="kw">loop</span> {
<span class="macro">print!</span>(<span class="string">&quot;Enter TOTP: &quot;</span>);
<span class="comment">// We flush stdout so it&#39;ll write the buffer to screen, continuing operation. Without it, the application halts.</span>
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Err</span>(<span class="ident">e</span>) <span class="op">=</span> <span class="ident">io::stdout</span>().<span class="ident">flush</span>() {
<span class="macro">error!</span>(<span class="string">&quot;Somehow we failed to flush stdout: {:?}&quot;</span>, <span class="ident">e</span>);
};
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">buffer</span> <span class="op">=</span> <span class="ident">String::new</span>();
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Err</span>(<span class="ident">e</span>) <span class="op">=</span> <span class="ident">io::stdin</span>().<span class="ident">read_line</span>(<span class="kw-2">&amp;mut</span> <span class="ident">buffer</span>) {
<span class="macro">error!</span>(<span class="string">&quot;Failed to read from stdin -&gt; {:?}&quot;</span>, <span class="ident">e</span>);
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">ClientError::SystemError</span>);
};
<span class="kw">let</span> <span class="ident">response</span> <span class="op">=</span> <span class="ident">buffer</span>.<span class="ident">trim</span>();
<span class="kw">match</span> <span class="ident">response</span>.<span class="ident">parse</span>::<span class="op">&lt;</span><span class="ident">u32</span><span class="op">&gt;</span>() {
<span class="prelude-val">Ok</span>(<span class="ident">i</span>) =&gt; <span class="kw">break</span> <span class="ident">i</span>,
<span class="prelude-val">Err</span>(<span class="kw">_</span>) =&gt; <span class="macro">eprintln!</span>(<span class="string">&quot;Invalid Number&quot;</span>),
};
};
<span class="ident">client</span>.<span class="ident">auth_step_totp</span>(<span class="ident">totp</span>).<span class="kw">await</span>
}
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">do_passkey</span>(
<span class="kw-2">&amp;</span><span class="self">self</span>,
<span class="ident">client</span>: <span class="kw-2">&amp;mut</span> <span class="ident">KanidmClient</span>,
<span class="ident">pkr</span>: <span class="ident">RequestChallengeResponse</span>,
) -&gt; <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">AuthResponse</span>, <span class="ident">ClientError</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">wa</span> <span class="op">=</span> <span class="ident">WebauthnAuthenticator::new</span>(<span class="ident">U2FHid::new</span>());
<span class="macro">println!</span>(<span class="string">&quot;Your authenticator will now flash for you to interact with it.&quot;</span>);
<span class="kw">let</span> <span class="ident">auth</span> <span class="op">=</span> <span class="ident">wa</span>
.<span class="ident">do_authentication</span>(<span class="ident">client</span>.<span class="ident">get_origin</span>().<span class="ident">clone</span>(), <span class="ident">pkr</span>)
.<span class="ident">unwrap_or_else</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> {
<span class="macro">error!</span>(<span class="string">&quot;Failed to interact with webauthn device. -- {:?}&quot;</span>, <span class="ident">e</span>);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
});
<span class="ident">client</span>.<span class="ident">auth_step_passkey_complete</span>(<span class="ident">auth</span>).<span class="kw">await</span>
}
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">do_securitykey</span>(
<span class="kw-2">&amp;</span><span class="self">self</span>,
<span class="ident">client</span>: <span class="kw-2">&amp;mut</span> <span class="ident">KanidmClient</span>,
<span class="ident">pkr</span>: <span class="ident">RequestChallengeResponse</span>,
) -&gt; <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="ident">AuthResponse</span>, <span class="ident">ClientError</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">wa</span> <span class="op">=</span> <span class="ident">WebauthnAuthenticator::new</span>(<span class="ident">U2FHid::new</span>());
<span class="macro">println!</span>(<span class="string">&quot;Your authenticator will now flash for you to interact with it.&quot;</span>);
<span class="kw">let</span> <span class="ident">auth</span> <span class="op">=</span> <span class="ident">wa</span>
.<span class="ident">do_authentication</span>(<span class="ident">client</span>.<span class="ident">get_origin</span>().<span class="ident">clone</span>(), <span class="ident">pkr</span>)
.<span class="ident">unwrap_or_else</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> {
<span class="macro">error!</span>(<span class="string">&quot;Failed to interact with webauthn device. -- {:?}&quot;</span>, <span class="ident">e</span>);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
});
<span class="ident">client</span>.<span class="ident">auth_step_securitykey_complete</span>(<span class="ident">auth</span>).<span class="kw">await</span>
}
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">exec</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">client</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">copt</span>.<span class="ident">to_unauth_client</span>();
<span class="comment">// TODO: remove this anon, nobody should do default anonymous</span>
<span class="kw">let</span> <span class="ident">username</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">copt</span>.<span class="ident">username</span>.<span class="ident">as_deref</span>().<span class="ident">unwrap_or</span>(<span class="string">&quot;anonymous&quot;</span>);
<span class="comment">// What auth mechanisms exist?</span>
<span class="kw">let</span> <span class="ident">mechs</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="kw">_</span><span class="op">&gt;</span> <span class="op">=</span> <span class="ident">client</span>
.<span class="ident">auth_step_init</span>(<span class="ident">username</span>)
.<span class="kw">await</span>
.<span class="ident">unwrap_or_else</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> {
<span class="macro">error!</span>(<span class="string">&quot;Error during authentication init phase: {:?}&quot;</span>, <span class="ident">e</span>);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
})
.<span class="ident">into_iter</span>()
.<span class="ident">collect</span>();
<span class="kw">let</span> <span class="ident">mech</span> <span class="op">=</span> <span class="kw">match</span> <span class="ident">mechs</span>.<span class="ident">len</span>() {
<span class="number">0</span> =&gt; {
<span class="macro">error!</span>(<span class="string">&quot;Error during authentication init phase: Server offered no authentication mechanisms&quot;</span>);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
}
<span class="number">1</span> =&gt;
{
<span class="attribute">#[<span class="ident">allow</span>(<span class="ident">clippy::expect_used</span>)]</span>
<span class="ident">mechs</span>
.<span class="ident">get</span>(<span class="number">0</span>)
.<span class="ident">expect</span>(<span class="string">&quot;can not fail - bounds already checked.&quot;</span>)
}
<span class="kw">_</span> =&gt; {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">options</span> <span class="op">=</span> <span class="ident">Vec::new</span>();
<span class="kw">for</span> <span class="ident">val</span> <span class="kw">in</span> <span class="ident">mechs</span>.<span class="ident">iter</span>() {
<span class="ident">options</span>.<span class="ident">push</span>(<span class="ident">val</span>.<span class="ident">to_string</span>());
}
<span class="kw">let</span> <span class="ident">msg</span> <span class="op">=</span> <span class="string">&quot;Please choose how you want to authenticate:&quot;</span>;
<span class="kw">let</span> <span class="ident">selection</span> <span class="op">=</span> <span class="ident">get_index_choice_dialoguer</span>(<span class="ident">msg</span>, <span class="kw-2">&amp;</span><span class="ident">options</span>);
<span class="attribute">#[<span class="ident">allow</span>(<span class="ident">clippy::expect_used</span>)]</span>
<span class="ident">mechs</span>
.<span class="ident">get</span>(<span class="ident">selection</span> <span class="kw">as</span> <span class="ident">usize</span>)
.<span class="ident">expect</span>(<span class="string">&quot;can not fail - bounds already checked.&quot;</span>)
}
};
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">allowed</span> <span class="op">=</span> <span class="ident">client</span>
.<span class="ident">auth_step_begin</span>((<span class="kw-2">*</span><span class="ident">mech</span>).<span class="ident">clone</span>())
.<span class="kw">await</span>
.<span class="ident">unwrap_or_else</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> {
<span class="macro">error!</span>(<span class="string">&quot;Error during authentication begin phase: {:?}&quot;</span>, <span class="ident">e</span>);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
});
<span class="comment">// We now have the first auth state, so we can proceed until complete.</span>
<span class="kw">loop</span> {
<span class="macro">debug!</span>(<span class="string">&quot;Allowed mechanisms -&gt; {:?}&quot;</span>, <span class="ident">allowed</span>);
<span class="comment">// What auth can proceed?</span>
<span class="kw">let</span> <span class="ident">choice</span> <span class="op">=</span> <span class="kw">match</span> <span class="ident">allowed</span>.<span class="ident">len</span>() {
<span class="number">0</span> =&gt; {
<span class="macro">error!</span>(
<span class="string">&quot;Error during authentication phase: Server offered no method to proceed&quot;</span>
);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
}
<span class="number">1</span> =&gt;
{
<span class="attribute">#[<span class="ident">allow</span>(<span class="ident">clippy::expect_used</span>)]</span>
<span class="ident">allowed</span>
.<span class="ident">get</span>(<span class="number">0</span>)
.<span class="ident">expect</span>(<span class="string">&quot;can not fail - bounds already checked.&quot;</span>)
}
<span class="kw">_</span> =&gt; {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">options</span> <span class="op">=</span> <span class="ident">Vec::new</span>();
<span class="kw">for</span> <span class="ident">val</span> <span class="kw">in</span> <span class="ident">allowed</span>.<span class="ident">iter</span>() {
<span class="ident">options</span>.<span class="ident">push</span>(<span class="ident">val</span>.<span class="ident">to_string</span>());
}
<span class="kw">let</span> <span class="ident">msg</span> <span class="op">=</span> <span class="string">&quot;Please choose what credential to provide:&quot;</span>;
<span class="kw">let</span> <span class="ident">selection</span> <span class="op">=</span> <span class="ident">get_index_choice_dialoguer</span>(<span class="ident">msg</span>, <span class="kw-2">&amp;</span><span class="ident">options</span>);
<span class="attribute">#[<span class="ident">allow</span>(<span class="ident">clippy::expect_used</span>)]</span>
<span class="ident">allowed</span>
.<span class="ident">get</span>(<span class="ident">selection</span> <span class="kw">as</span> <span class="ident">usize</span>)
.<span class="ident">expect</span>(<span class="string">&quot;can not fail - bounds already checked.&quot;</span>)
}
};
<span class="kw">let</span> <span class="ident">res</span> <span class="op">=</span> <span class="kw">match</span> <span class="ident">choice</span> {
<span class="ident">AuthAllowed::Anonymous</span> =&gt; <span class="ident">client</span>.<span class="ident">auth_step_anonymous</span>().<span class="kw">await</span>,
<span class="ident">AuthAllowed::Password</span> =&gt; <span class="self">self</span>.<span class="ident">do_password</span>(<span class="kw-2">&amp;mut</span> <span class="ident">client</span>).<span class="kw">await</span>,
<span class="ident">AuthAllowed::BackupCode</span> =&gt; <span class="self">self</span>.<span class="ident">do_backup_code</span>(<span class="kw-2">&amp;mut</span> <span class="ident">client</span>).<span class="kw">await</span>,
<span class="ident">AuthAllowed::Totp</span> =&gt; <span class="self">self</span>.<span class="ident">do_totp</span>(<span class="kw-2">&amp;mut</span> <span class="ident">client</span>).<span class="kw">await</span>,
<span class="ident">AuthAllowed::Passkey</span>(<span class="ident">chal</span>) =&gt; <span class="self">self</span>.<span class="ident">do_passkey</span>(<span class="kw-2">&amp;mut</span> <span class="ident">client</span>, <span class="ident">chal</span>.<span class="ident">clone</span>()).<span class="kw">await</span>,
<span class="ident">AuthAllowed::SecurityKey</span>(<span class="ident">chal</span>) =&gt; {
<span class="self">self</span>.<span class="ident">do_securitykey</span>(<span class="kw-2">&amp;mut</span> <span class="ident">client</span>, <span class="ident">chal</span>.<span class="ident">clone</span>()).<span class="kw">await</span>
}
};
<span class="comment">// Now update state.</span>
<span class="kw">let</span> <span class="ident">state</span> <span class="op">=</span> <span class="ident">res</span>
.<span class="ident">unwrap_or_else</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> {
<span class="macro">error!</span>(<span class="string">&quot;Error in authentication phase: {:?}&quot;</span>, <span class="ident">e</span>);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
})
.<span class="ident">state</span>;
<span class="comment">// What auth state are we in?</span>
<span class="ident">allowed</span> <span class="op">=</span> <span class="kw">match</span> <span class="kw-2">&amp;</span><span class="ident">state</span> {
<span class="ident">AuthState::Continue</span>(<span class="ident">allowed</span>) =&gt; <span class="ident">allowed</span>.<span class="ident">to_vec</span>(),
<span class="ident">AuthState::Success</span>(<span class="ident">_token</span>) =&gt; <span class="kw">break</span>,
<span class="ident">AuthState::Denied</span>(<span class="ident">reason</span>) =&gt; {
<span class="macro">error!</span>(<span class="string">&quot;Authentication Denied: {:?}&quot;</span>, <span class="ident">reason</span>);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
}
<span class="kw">_</span> =&gt; {
<span class="macro">error!</span>(<span class="string">&quot;Error in authentication phase: invalid authstate&quot;</span>);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
}
};
<span class="comment">// Loop again.</span>
}
<span class="comment">// Read the current tokens</span>
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">tokens</span> <span class="op">=</span> <span class="ident">read_tokens</span>().<span class="ident">unwrap_or_else</span>(<span class="op">|</span><span class="kw">_</span><span class="op">|</span> {
<span class="macro">error!</span>(<span class="string">&quot;Error retrieving authentication token store&quot;</span>);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
});
<span class="comment">// Add our new one</span>
<span class="kw">match</span> <span class="ident">client</span>.<span class="ident">get_token</span>().<span class="kw">await</span> {
<span class="prelude-val">Some</span>(<span class="ident">t</span>) =&gt; <span class="ident">tokens</span>.<span class="ident">insert</span>(<span class="ident">username</span>.<span class="ident">to_string</span>(), <span class="ident">t</span>),
<span class="prelude-val">None</span> =&gt; {
<span class="macro">error!</span>(<span class="string">&quot;Error retrieving client session&quot;</span>);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
}
};
<span class="comment">// write them out.</span>
<span class="kw">if</span> <span class="ident">write_tokens</span>(<span class="kw-2">&amp;</span><span class="ident">tokens</span>).<span class="ident">is_err</span>() {
<span class="macro">error!</span>(<span class="string">&quot;Error persisting authentication token store&quot;</span>);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
};
<span class="comment">// Success!</span>
<span class="macro">println!</span>(<span class="string">&quot;Login Success for {}&quot;</span>, <span class="ident">username</span>);
}
}
<span class="kw">impl</span> <span class="ident">LogoutOpt</span> {
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">debug</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="ident">bool</span> {
<span class="self">self</span>.<span class="ident">copt</span>.<span class="ident">debug</span>
}
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">exec</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) {
<span class="kw">let</span> <span class="ident">username</span>: <span class="ident">String</span> <span class="op">=</span> <span class="kw">if</span> <span class="self">self</span>.<span class="ident">local_only</span> {
<span class="comment">// For now we just remove this from the token store.</span>
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">_tmp_username</span> <span class="op">=</span> <span class="ident">String::new</span>();
<span class="kw">match</span> <span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">copt</span>.<span class="ident">username</span> {
<span class="prelude-val">Some</span>(<span class="ident">value</span>) =&gt; <span class="ident">value</span>.<span class="ident">clone</span>(),
<span class="prelude-val">None</span> =&gt; <span class="kw">match</span> <span class="ident">prompt_for_username_get_username</span>() {
<span class="prelude-val">Ok</span>(<span class="ident">value</span>) =&gt; <span class="ident">value</span>,
<span class="prelude-val">Err</span>(<span class="ident">msg</span>) =&gt; {
<span class="macro">error!</span>(<span class="string">&quot;{}&quot;</span>, <span class="ident">msg</span>);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
}
},
}
} <span class="kw">else</span> {
<span class="kw">let</span> <span class="ident">client</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">copt</span>.<span class="ident">to_client</span>().<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">token</span> <span class="op">=</span> <span class="kw">match</span> <span class="ident">client</span>.<span class="ident">get_token</span>().<span class="kw">await</span> {
<span class="prelude-val">Some</span>(<span class="ident">t</span>) =&gt; <span class="ident">t</span>,
<span class="prelude-val">None</span> =&gt; {
<span class="macro">error!</span>(<span class="string">&quot;Client token store is empty/corrupt&quot;</span>);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
}
};
<span class="comment">// Parse it for the username.</span>
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Err</span>(<span class="ident">e</span>) <span class="op">=</span> <span class="ident">client</span>.<span class="ident">logout</span>().<span class="kw">await</span> {
<span class="macro">error!</span>(<span class="string">&quot;Failed to logout - {:?}&quot;</span>, <span class="ident">e</span>);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
}
<span class="comment">// Server acked the logout, lets proceed with the local cleanup now.</span>
<span class="kw">let</span> <span class="ident">jwtu</span> <span class="op">=</span> <span class="kw">match</span> <span class="ident">JwsUnverified::from_str</span>(<span class="kw-2">&amp;</span><span class="ident">token</span>) {
<span class="prelude-val">Ok</span>(<span class="ident">value</span>) =&gt; <span class="ident">value</span>,
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; {
<span class="macro">error!</span>(<span class="question-mark">?</span><span class="ident">e</span>, <span class="string">&quot;Unable to parse token from str&quot;</span>);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
}
};
<span class="kw">let</span> <span class="ident">uat</span>: <span class="ident">UserAuthToken</span> <span class="op">=</span> <span class="kw">match</span> <span class="ident">jwtu</span>.<span class="ident">validate_embeded</span>() {
<span class="prelude-val">Ok</span>(<span class="ident">jwt</span>) =&gt; <span class="ident">jwt</span>.<span class="ident">into_inner</span>(),
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; {
<span class="macro">error!</span>(<span class="question-mark">?</span><span class="ident">e</span>, <span class="string">&quot;Unable to verify token signature, may be corrupt&quot;</span>);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
}
};
<span class="ident">uat</span>.<span class="ident">name</span>().<span class="ident">to_string</span>()
};
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">tokens</span> <span class="op">=</span> <span class="ident">read_tokens</span>().<span class="ident">unwrap_or_else</span>(<span class="op">|</span><span class="kw">_</span><span class="op">|</span> {
<span class="macro">error!</span>(<span class="string">&quot;Error retrieving authentication token store&quot;</span>);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
});
<span class="comment">// Remove our old one</span>
<span class="kw">if</span> <span class="ident">tokens</span>.<span class="ident">remove</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>).<span class="ident">is_some</span>() {
<span class="comment">// write them out.</span>
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Err</span>(<span class="ident">_e</span>) <span class="op">=</span> <span class="ident">write_tokens</span>(<span class="kw-2">&amp;</span><span class="ident">tokens</span>) {
<span class="macro">error!</span>(<span class="string">&quot;Error persisting authentication token store&quot;</span>);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
};
<span class="macro">println!</span>(<span class="string">&quot;Removed session for {}&quot;</span>, <span class="ident">username</span>);
} <span class="kw">else</span> {
<span class="macro">println!</span>(<span class="string">&quot;No sessions for {}&quot;</span>, <span class="ident">username</span>);
}
}
}
<span class="kw">impl</span> <span class="ident">SessionOpt</span> {
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">debug</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="ident">bool</span> {
<span class="kw">match</span> <span class="self">self</span> {
<span class="ident">SessionOpt::List</span>(<span class="ident">dopt</span>) <span class="op">|</span> <span class="ident">SessionOpt::Cleanup</span>(<span class="ident">dopt</span>) =&gt; <span class="ident">dopt</span>.<span class="ident">debug</span>,
}
}
<span class="kw">fn</span> <span class="ident">read_valid_tokens</span>() -&gt; <span class="ident">BTreeMap</span><span class="op">&lt;</span><span class="ident">String</span>, (<span class="ident">String</span>, <span class="ident">UserAuthToken</span>)<span class="op">&gt;</span> {
<span class="ident">read_tokens</span>()
.<span class="ident">unwrap_or_else</span>(<span class="op">|</span><span class="kw">_</span><span class="op">|</span> {
<span class="macro">error!</span>(<span class="string">&quot;Error retrieving authentication token store&quot;</span>);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
})
.<span class="ident">into_iter</span>()
.<span class="ident">filter_map</span>(<span class="op">|</span>(<span class="ident">u</span>, <span class="ident">t</span>)<span class="op">|</span> {
<span class="kw">let</span> <span class="ident">jwtu</span> <span class="op">=</span> <span class="ident">JwsUnverified::from_str</span>(<span class="kw-2">&amp;</span><span class="ident">t</span>)
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> {
<span class="macro">error!</span>(<span class="question-mark">?</span><span class="ident">e</span>, <span class="string">&quot;Unable to parse token from str&quot;</span>);
})
.<span class="ident">ok</span>()<span class="question-mark">?</span>;
<span class="ident">jwtu</span>.<span class="ident">validate_embeded</span>()
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> {
<span class="macro">error!</span>(<span class="question-mark">?</span><span class="ident">e</span>, <span class="string">&quot;Unable to verify token signature, may be corrupt&quot;</span>);
})
.<span class="ident">map</span>(<span class="op">|</span><span class="ident">jwt</span><span class="op">|</span> {
<span class="kw">let</span> <span class="ident">uat</span> <span class="op">=</span> <span class="ident">jwt</span>.<span class="ident">into_inner</span>();
(<span class="ident">u</span>, (<span class="ident">t</span>, <span class="ident">uat</span>))
})
.<span class="ident">ok</span>()
})
.<span class="ident">collect</span>()
}
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">exec</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) {
<span class="kw">match</span> <span class="self">self</span> {
<span class="ident">SessionOpt::List</span>(<span class="kw">_</span>) =&gt; {
<span class="kw">let</span> <span class="ident">tokens</span> <span class="op">=</span> <span class="ident"><span class="self">Self</span>::read_valid_tokens</span>();
<span class="kw">for</span> (<span class="kw">_</span>, <span class="ident">uat</span>) <span class="kw">in</span> <span class="ident">tokens</span>.<span class="ident">values</span>() {
<span class="macro">println!</span>(<span class="string">&quot;---&quot;</span>);
<span class="macro">println!</span>(<span class="string">&quot;{}&quot;</span>, <span class="ident">uat</span>);
}
}
<span class="ident">SessionOpt::Cleanup</span>(<span class="kw">_</span>) =&gt; {
<span class="kw">let</span> <span class="ident">tokens</span> <span class="op">=</span> <span class="ident"><span class="self">Self</span>::read_valid_tokens</span>();
<span class="kw">let</span> <span class="ident">start_len</span> <span class="op">=</span> <span class="ident">tokens</span>.<span class="ident">len</span>();
<span class="kw">let</span> <span class="ident">now</span> <span class="op">=</span> <span class="ident">time::OffsetDateTime::now_utc</span>();
<span class="kw">let</span> <span class="ident">tokens</span>: <span class="ident">BTreeMap</span><span class="op">&lt;</span><span class="kw">_</span>, <span class="kw">_</span><span class="op">&gt;</span> <span class="op">=</span> <span class="ident">tokens</span>
.<span class="ident">into_iter</span>()
.<span class="ident">filter_map</span>(<span class="op">|</span>(<span class="ident">u</span>, (<span class="ident">t</span>, <span class="ident">uat</span>))<span class="op">|</span> {
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">exp</span>) <span class="op">=</span> <span class="ident">uat</span>.<span class="ident">expiry</span> {
<span class="kw">if</span> <span class="ident">now</span> <span class="op">&gt;</span><span class="op">=</span> <span class="ident">exp</span> {
<span class="comment">//Expired</span>
<span class="prelude-val">None</span>
} <span class="kw">else</span> {
<span class="prelude-val">Some</span>((<span class="ident">u</span>, <span class="ident">t</span>))
}
} <span class="kw">else</span> {
<span class="prelude-val">Some</span>((<span class="ident">u</span>, <span class="ident">t</span>))
}
})
.<span class="ident">collect</span>();
<span class="kw">let</span> <span class="ident">end_len</span> <span class="op">=</span> <span class="ident">tokens</span>.<span class="ident">len</span>();
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Err</span>(<span class="ident">_e</span>) <span class="op">=</span> <span class="ident">write_tokens</span>(<span class="kw-2">&amp;</span><span class="ident">tokens</span>) {
<span class="macro">error!</span>(<span class="string">&quot;Error persisting authentication token store&quot;</span>);
<span class="ident">std::process::exit</span>(<span class="number">1</span>);
};
<span class="macro">println!</span>(<span class="string">&quot;Removed {} sessions&quot;</span>, <span class="ident">start_len</span> <span class="op">-</span> <span class="ident">end_len</span>);
}
}
}
}
</code></pre></div>
</section></div></main><div id="rustdoc-vars" data-root-path="../../" data-current-crate="kanidm_cli" data-themes="ayu,dark,light" data-resource-suffix="" data-rustdoc-version="1.64.0 (a55dd71d5 2022-09-19)" ></div></body></html>