codex_cli/auth/
current.rs1use anyhow::Result;
2use std::path::Path;
3
4use crate::auth;
5use crate::fs;
6use crate::paths;
7
8pub fn run() -> Result<i32> {
9 let auth_file = match paths::resolve_auth_file() {
10 Some(path) => path,
11 None => return Ok(1),
12 };
13
14 if !auth_file.is_file() {
15 eprintln!("codex: {} not found", auth_file.display());
16 return Ok(1);
17 }
18
19 let auth_key = auth::identity_key_from_auth_file(&auth_file).ok().flatten();
20 let auth_hash = match fs::sha256_file(&auth_file) {
21 Ok(hash) => hash,
22 Err(_) => {
23 eprintln!("codex: failed to hash {}", auth_file.display());
24 return Ok(1);
25 }
26 };
27
28 let secret_dir = paths::resolve_secret_dir();
29 let mut matched: Option<(String, MatchMode)> = None;
30
31 if let Some(secret_dir) = secret_dir
32 && let Ok(entries) = std::fs::read_dir(&secret_dir)
33 {
34 for entry in entries.flatten() {
35 let path = entry.path();
36 if path.extension().and_then(|s| s.to_str()) != Some("json") {
37 continue;
38 }
39
40 if let Some(key) = auth_key.as_deref()
41 && let Ok(Some(candidate_key)) = auth::identity_key_from_auth_file(&path)
42 && candidate_key == key
43 {
44 let candidate_hash = match fs::sha256_file(&path) {
45 Ok(hash) => hash,
46 Err(_) => {
47 eprintln!("codex: failed to hash {}", path.display());
48 return Ok(1);
49 }
50 };
51 let mode = if candidate_hash == auth_hash {
52 MatchMode::Exact
53 } else {
54 MatchMode::Identity
55 };
56 matched = Some((file_name(&path), mode));
57 break;
58 }
59
60 let candidate_hash = match fs::sha256_file(&path) {
61 Ok(hash) => hash,
62 Err(_) => {
63 eprintln!("codex: failed to hash {}", path.display());
64 return Ok(1);
65 }
66 };
67 if candidate_hash == auth_hash {
68 matched = Some((file_name(&path), MatchMode::Exact));
69 break;
70 }
71 }
72 }
73
74 if let Some((secret_name, mode)) = matched {
75 match mode {
76 MatchMode::Exact => {
77 println!("codex: {} matches {}", auth_file.display(), secret_name);
78 }
79 MatchMode::Identity => {
80 println!(
81 "codex: {} matches {} (identity; secret differs)",
82 auth_file.display(),
83 secret_name
84 );
85 }
86 }
87 return Ok(0);
88 }
89
90 println!(
91 "codex: {} does not match any known secret",
92 auth_file.display()
93 );
94 Ok(2)
95}
96
97#[derive(Copy, Clone)]
98enum MatchMode {
99 Exact,
100 Identity,
101}
102
103fn file_name(path: &Path) -> String {
104 path.file_name()
105 .and_then(|name| name.to_str())
106 .unwrap_or_default()
107 .to_string()
108}