/* Copyright 2005 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: hproxy.c,v 1.7 2005/06/30 14:25:49 lwa Exp $"; #include #include #include /* redefine system struct passwd */ #define passwd system_passwd #include #undef passwd #include #include #include #include #if HAVE_STDINT_H #include #endif #include #include "hparam.h" static void hproxy_clean(void) { return; } static char * hproxy_query(char *entry) { extern struct param home_param; int s; char *buf; char *path = home_param.proxy_socket; struct sockaddr_un sa_un; uint32_t len; ssize_t readlen; if (path && *path == '$') { path = getenv(path +1); } if (path == NULL || *path == 0) { path = "/var/run/home_proxy"; } s = socket(AF_UNIX, SOCK_STREAM, 0); if (s == -1) { home_retry("unable to open socket: %s", strerror(errno)); return NULL; } memset(&sa_un, 0, sizeof(struct sockaddr_un)); sa_un.sun_family = AF_UNIX; sa_un.sun_path[0] = 0; strncat(sa_un.sun_path, path, sizeof(sa_un.sun_path)-1); if (connect(s, (struct sockaddr *)&sa_un, sizeof(sa_un)) == -1) { close(s); home_retry("unable to connect to socket %s: %s", path, strerror(errno)); return NULL; } if (write(s, entry, strlen(entry) + 1) == 0) { close(s); home_retry("unable to write to socket %s: %s", path, strerror(errno)); return NULL; } shutdown(s, SHUT_WR); readlen = read(s, &len, sizeof(len)); if (readlen != sizeof(len)) { home_retry("proxy read length mismatch (%lu != %lu)", (unsigned long)sizeof(len), (unsigned long)readlen); close(s); return NULL; } if (len == 0) { close(s); return NULL; } if (len == 0xFFFFFFFF) { close(s); home_retry("proxy transcient error"); return NULL; } buf = malloc(len); if (buf == NULL) { close(s); home_retry("unable to allocate %lu bytes: %s", (unsigned long)len, strerror(errno)); return NULL; } readlen = read(s, buf, len); if (readlen != len) { home_retry("proxy read length mismatch (%lu != %lu)", (unsigned long)len, (unsigned long)readlen); free(buf); close(s); return NULL; } close(s); return buf; } static struct passwd * hproxy_store(char *res, char **alias) { struct passwd *pwd; char *buf = res; if (buf == NULL) return NULL; pwd = home_getpwd(); pwd->pw_name = strdup(res); res = strchr(res, 0); res ++; pwd->pw_passwd = strdup(res); res = strchr(res, 0); res ++; pwd->pw_uid=*res ? (uid_t)strtoul(res, NULL, 10) : (uid_t)-1; res = strchr(res, 0); res ++; pwd->pw_gid=*res ? (gid_t)strtoul(res, NULL, 10) : (gid_t)-1; res = strchr(res, 0); res ++; #ifdef HAS_PW_CLASS pwd->pw_class = strdup(res); #endif res = strchr(res, 0); res ++; pwd->pw_gecos = strdup(res); res = strchr(res, 0); res ++; pwd->pw_dir = strdup(res); res = strchr(res, 0); res ++; pwd->pw_shell = strdup(res); res = strchr(res, 0); res ++; #ifdef HAS_PW_CHANGE pwd->pw_change=0; #endif #ifdef HAS_PW_EXPIRE pwd->pw_expire=*res ? (gid_t)strtoul(res, NULL, 10) : 0; #endif res = strchr(res, 0); res ++; #ifdef HAS_PW_FIELDS /* internal FreeBSD */ #endif #ifdef HAS_PW_QUOTA pwd->pw_quota= *res ? (int)strtol(res, NULL, 10) : 0; #endif free(buf); return pwd; } struct home_driver hproxy_driver = { (home_query_t) hproxy_query, (home_store_t) hproxy_store, (home_clean_t) hproxy_clean, };