diff --git a/accesser/utils/certmanager.py b/accesser/utils/certmanager.py index f50c709..37df450 100644 --- a/accesser/utils/certmanager.py +++ b/accesser/utils/certmanager.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import os +import os, platform import datetime from pathlib import Path @@ -33,14 +33,53 @@ ) from cryptography.x509.oid import ExtendedKeyUsageOID +from .log import logger +logger = logger.getChild("certmanager") from . import setting from .setting import basepath -if setting.config["importca"]: - certpath = os.path.join(basepath, "CERT") -else: - certpath = "CERT" -if not os.path.exists(certpath): + +def decide_state_path_legacy(): + if setting.config["importca"]: + return Path(basepath) + else: + return Path() + + +def decide_state_path_unix_like(): + if os.geteuid() == 0: + logger.warn("Running Accesser as the root user carries certain risks; see pull #245") + return Path("/var/lib") / "accesser" + + state_path = os.getenv("XDG_STATE_HOME", None) + if state_path is not None: + state_path = Path(state_path) / "accesser" + else: + state_path = Path.home() / ".local/state" / "accesser" + return state_path + + +def decide_certpath(): + certpath = None + # 人为指定最优先 + #if setting.config["state_dir"]: + #return Path(setting.config["state_dir"]) / "cert" + match platform.system(): + case 'Linux' | 'FreeBSD': + deprecated_path = decide_state_path_legacy() / "CERT" + # 暂仅在 *nix 上视为已废弃 + if deprecated_path.exists(): + logger.warn("deprecated path, see pull #245") + return deprecated_path + certpath = decide_state_path_unix_like() / "cert" + case _: + # windows,mac,android ... + certpath = decide_state_path_legacy() / "CERT" + return certpath + + +certpath = decide_certpath() +if not certpath.exists(): os.makedirs(certpath, exist_ok=True) @@ -92,11 +131,11 @@ def create_root_ca(): .sign(key, hashes.SHA256()) ) - (Path(certpath) / "root.crt").write_bytes( + (certpath / "root.crt").write_bytes( cert.public_bytes(serialization.Encoding.PEM) ) - (Path(certpath) / "root.key").write_bytes( + (certpath / "root.key").write_bytes( key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, @@ -104,7 +143,7 @@ def create_root_ca(): ) ) - (Path(certpath) / "root.pfx").write_bytes( + (certpath / "root.pfx").write_bytes( serialization.pkcs12.serialize_key_and_certificates( b"Accesser", key, cert, None, serialization.NoEncryption() ) @@ -112,8 +151,8 @@ def create_root_ca(): def create_certificate(server_name): - rootpem = (Path(certpath) / "root.crt").read_bytes() - rootkey = (Path(certpath) / "root.key").read_bytes() + rootpem = (certpath / "root.crt").read_bytes() + rootkey = (certpath / "root.key").read_bytes() ca_cert = x509.load_pem_x509_certificate(rootpem) pkey = serialization.load_pem_private_key(rootkey, password=None) @@ -180,7 +219,7 @@ def create_certificate(server_name): .sign(pkey, hashes.SHA256()) ) - (Path(certpath) / f"{server_name}.crt").write_bytes( + (certpath / f"{server_name}.crt").write_bytes( cert.public_bytes(serialization.Encoding.PEM) + pkey.private_bytes( encoding=serialization.Encoding.PEM, diff --git a/accesser/utils/importca.py b/accesser/utils/importca.py index 94a46a6..6b7380c 100644 --- a/accesser/utils/importca.py +++ b/accesser/utils/importca.py @@ -17,6 +17,7 @@ # along with this program. If not, see . import os, sys +from pathlib import Path import subprocess import locale @@ -25,14 +26,10 @@ from . import setting from . import certmanager as cm -from .setting import basepath from .log import logger logger = logger.getChild('importca') -if setting.config['importca']: - certpath = os.path.join(basepath, 'CERT') -else: - certpath = 'CERT' +certpath = cm.certpath def logandrun(cmd): if hasattr(subprocess, 'STARTUPINFO'): diff --git a/accesser/utils/setting.py b/accesser/utils/setting.py index 7c9e74e..6b871ff 100644 --- a/accesser/utils/setting.py +++ b/accesser/utils/setting.py @@ -71,8 +71,18 @@ def parse_args(): action="store_true", help="do not import certificate to system automatically", ) + parser.add_argument( + "--state-dir", + type=str, + help="where state file store , override notimportca", + default=None, + ) args = parser.parse_args() if args.notsetproxy: config["setproxy"] = False + return + # FIXME Wrong initialization sequence + # see pull #245 if args.notimportca: config["importca"] = False + config["state_dir"] = args.state_dir