use crate::config::{ argv_to_config, get_config }; use config::Config; use oauth2::{ AuthUrl, ClientId, ClientSecret, ResourceOwnerPassword, ResourceOwnerUsername, Scope, TokenUrl }; use oauth2::basic::{ BasicClient, BasicTokenResponse }; use oauth2::reqwest::http_client; extern crate pamsm; use pamsm::{PamServiceModule, Pam, PamFlag, PamError, PamLibExt}; fn get_or_pam_error(config: &Config, key: &str) -> Result<String, PamError> { match config.get_str(key) { Ok(v) => Ok(v), _ => Err(PamError::SERVICE_ERR), } } fn do_legacy_auth(username: String, password: String, config: Config) -> Result<BasicTokenResponse, PamError> { let client_id = ClientId::new(get_or_pam_error(&config, "pam.client_id")?); let client_secret = ClientSecret::new(get_or_pam_error(&config, "pam.client_secret")?); let auth_url = match AuthUrl::new(get_or_pam_error(&config, "pam.auth_url")?) { Ok(u) => u, _ => return Err(PamError::SERVICE_ERR), }; let token_url = match TokenUrl::new(get_or_pam_error(&config, "pam.token_url")?){ Ok(u) => u, _ => return Err(PamError::SERVICE_ERR), }; let scope = get_or_pam_error(&config, "pam.scope")?; let client = BasicClient::new(client_id, Some(client_secret), auth_url, Some(token_url)); match client .exchange_password( &ResourceOwnerUsername::new(username), &ResourceOwnerPassword::new(password) ) .add_scope(Scope::new(scope.to_string())) .request(http_client) { Ok(t) => Ok(t), _ => Err(PamError::AUTHINFO_UNAVAIL), } } struct PamOidc; impl PamServiceModule for PamOidc { fn authenticate(pamh: Pam, _: PamFlag, argv: Vec<String>) -> PamError { let conf_args = argv_to_config(argv); let conf = get_config(conf_args); if conf.get_str("pam.flow").unwrap() == "password" { let username = match pamh.get_user(None) { Ok(Some(u)) => match u.to_str() { Ok(u) => u, _ => return PamError::CRED_INSUFFICIENT, }, Ok(None) => return PamError::CRED_INSUFFICIENT, Err(e) => return e, }; let password = match pamh.get_authtok(None) { Ok(Some(p)) => match p.to_str() { Ok(p) => p, _ => return PamError::CRED_INSUFFICIENT, }, Ok(None) => return PamError::CRED_INSUFFICIENT, Err(e) => return e, }; match do_legacy_auth(username.to_string(), password.to_string(), conf) { Ok(_) => return PamError::SUCCESS, Err(e) => return e, }; } return PamError::SERVICE_ERR; } }