/* Copyright 2000, 2001, 2002 Laurent Wacrenier This file is part of libhome libhome is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. libhome is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with libhome; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" static char const rcsid[] UNUSED = "$Id: hpam.c,v 1.3 2005/06/23 13:02:59 lwa Exp $"; #include #include #include #include #include #include "hparam.h" extern struct param home_param; static int conv(int n, const struct pam_message ** msg, struct pam_response **resp, void *data) { struct pam_response *rep = calloc(n, sizeof(struct pam_response)); int ret = PAM_SUCCESS; int i; if (rep == NULL) { home_retry("PAM conv: %s", strerror(errno)); return PAM_BUF_ERR; } for (i=0; imsg_style) { case PAM_PROMPT_ECHO_OFF: home_retry("PAM conv recieve suspicious echo off"); ret = PAM_CONV_ERR; break; case PAM_PROMPT_ECHO_ON: home_retry("PAM conv recieve suspicious echo on"); ret = PAM_CONV_ERR; break; case PAM_ERROR_MSG: { home_error("PAM error: %s", msg[i]->msg); ret = PAM_CONV_ERR; break; } case PAM_TEXT_INFO: home_error("PAM info: %s", msg[i]->msg); break; } rep[i].resp_retcode = 0; rep[i].resp = NULL; } *resp = rep; return ret; } static pam_handle_t *hpam_query(char *rentry) { pam_handle_t *ph; int err; struct pam_conv pc = { conv, NULL }; if (IS_UID(rentry)) return NULL; err = pam_start(home_param.pam_service, rentry, &pc, &ph); if (err != PAM_SUCCESS) { home_retry("PAM start error: %s", pam_strerror(ph, err)); pam_end(ph, 0); errno = ENOMEM; return NULL; } err = pam_acct_mgmt(ph, 0); switch(err) { case PAM_SUCCESS: return ph; case PAM_SYSTEM_ERR: case PAM_BUF_ERR: errno = ENOMEM; pam_end(ph, 0); return NULL; default: errno = 0; pam_end(ph, 0); return NULL; } } static struct passwd *hpam_store(pam_handle_t *ph, char **alias) { *alias = NULL; struct passwd *pwd; char *user; pam_get_item(ph, PAM_USER, (const void **)&user); pwd = home_getpwd(); pwd->pw_name = strdup(user); pwd->pw_passwd = strdup(home_param.pw_passwd ? home_param.pw_passwd : "*"); pwd->pw_uid = home_param.pw_uid ? home_calc(strtol(home_param.pw_uid, NULL, 10), home_param.uid_calc) : -1; pwd->pw_gid = home_param.pw_gid ? strtol(home_param.pw_gid, NULL, 10) : -1; #ifdef HAS_PW_CLASS pwd->pw_class=strdup(home_param.pw_class ? home_param.pw_class : ""); #endif pwd->pw_gecos=strdup(home_param.pw_gecos ? home_param.pw_gecos : ""); pwd->pw_dir = hexpand_home(user, home_param.pw_dir ? home_param.pw_dir : ""); pwd->pw_shell=strdup(home_param.pw_shell ? home_param.pw_shell : ""); #ifdef HAS_PW_CHANGE pwd->pw_change=0; #endif #ifdef HAS_PW_EXPIRE if (home_param.pw_expire) { pwd->pw_expire = home_expire(home_param.pw_expire); } else { pwd->pw_expire = 0; } #endif #ifdef HAS_PW_FIELDS /* internal FreeBSD */ #endif #ifdef HAS_PW_QUOTA if (home_param.pw_quota) { pwd->pw_quota = strtol(home_param.pw_quota, NULL, 10); pwd->pw_quota *= home_param.quota_unit; } else { pwd->pw_quota = 0; } #endif pam_end(ph, 0); return pwd; } void hpam_clean(void) { return; } struct home_driver hpam_driver = { (home_query_t) hpam_query, (home_store_t) hpam_store, (home_clean_t) hpam_clean, };