/* * Copyright (c) 2004, 2005 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include "sm/generic.h" SM_RCSID("@(#)$Id: passwd.c,v 1.15 2006/10/05 04:27:38 ca Exp $") #include "sm/assert.h" #include "sm/error.h" #include "sm/memops.h" #include "sm/heap.h" #include "sm/types.h" #include "map.h" #include "sm/map.h" #include "sm/maps.h" #include "sm/mapc.h" #include "sm/mapclasses.h" #include "sm/pwd.h" #if 0 #include "sm/io.h" #endif /* 0 */ /* static sm_map_open_F sm_passwd_open; */ /* static sm_map_close_F sm_passwd_close; */ static sm_map_alloc_F sm_passwd_alloc; static sm_map_free_F sm_passwd_free; static sm_map_locate_F sm_passwd_locate; static sm_map_first_F sm_passwd_first; static sm_map_next_F sm_passwd_next; /* ** MAP_SETOPT -- set options for map ** ** Parameters: ** map -- map ** ap -- options ** ** Returns: ** usual sm_error code */ static sm_ret_T sm_passwd_setopt(sm_map_P map, va_list ap) { SM_IS_MAP(map); return SM_SUCCESS; } /* ** MAP_GETOPT -- get options for map ** ** Parameters: ** map -- map ** which -- which option? ** valp -- pointer to place where result should be stored ** ** Returns: ** usual sm_error code */ static sm_ret_T sm_passwd_getopt(sm_map_P map, int which, void *valp) { SM_IS_MAP(map); return SM_SUCCESS; } /* ** MAP_CLOSE -- close map ** XXX more parameters... ** ** Parameters: ** map -- map ** flags -- flags ** ** Returns: ** usual sm_error code */ static sm_ret_T sm_passwd_close(sm_map_P map, uint32_t flags) { return SM_SUCCESS; } /* ** MAP_CREATE -- create map ** ** Parameters: ** pmap -- pointer to map (output) ** flags -- flags ** ** Returns: ** usual sm_error code */ static sm_ret_T sm_passwd_create(sm_mapc_P mapc, const sm_cstr_P type, uint32_t flags, sm_map_P map) { SM_IS_MAPC(mapc); SM_REQUIRE(map != NULL); map->sm_map_caps = SMMAP_CAPS_LOCALPART; return SM_SUCCESS; } /* ** MAP_OPEN -- open map ** ** Parameters: ** mapc -- map context ** type -- type of map (currently ignored) ** flags -- flags for map (currently ignored) ** path -- path of map (currently ignored) ** mode -- open mode (currently ignored) ** map -- map ** ap -- additional argument ** ** Returns: ** usual sm_error code */ static sm_ret_T sm_passwd_open(sm_mapc_P mapc, const sm_cstr_P type, uint32_t flags, const char *path, int mode, sm_map_P map, va_list ap) { SM_IS_MAPC(mapc); SM_REQUIRE(map != NULL); #if 0 db = map->sm_map_db; for (;;) { k = va_arg(ap, uint); if (k == SMPO_END) break; switch (k) { case SMPO_MAX_ELEM: u = va_arg(ap, uint); db->passwd_limit = u; break; case SMPO_HASH_NELEM: u = va_arg(ap, uint); db->passwd_size = u; break; default: /* silently ignore bogus options? */ break; } } ret = passwd_open(&db); if (sm_is_err(ret)) goto error; #endif /* 0 */ return SM_SUCCESS; #if 0 error: if (db != NULL) { (void) passwd_destroy(db, NULL, NULL); db = NULL; } return ret; #endif /* 0 */ } /* ** SM_PASSWD_LOOKUP -- lookup a key in PASSWD, return data if found ** ** Parameters: ** map -- map context ** flags -- flags ** key -- key ** data -- data (output) ** ** Returns: ** usual sm_error code */ static sm_ret_T sm_passwd_lookup(sm_map_P map, uint32_t flags, sm_map_key_P key, sm_map_data_P data) { sm_ret_T ret; int r; sm_mapc_P mapc; struct passwd *pwent; #if MTA_USE_PTHREADS && HAVE_GETPWNAM_R struct passwd pwentb; char buf[1024]; #endif SM_IS_MAP(map); SM_IS_KEY(key); SM_IS_DATA(data); mapc = map->sm_map_class; SM_IS_MAPC(mapc); ret = SM_SUCCESS; if (!SMMAP_IS_FL(map, SMMAP_FL_OPEN)) { /* map closed but can be reopened? */ if (mapc->sm_mapc_reopenf != NULL) ret = mapc->sm_mapc_reopenf(map, 0); else ret = sm_error_perm(SM_EM_MAP, SM_E_CLOSEDMAP); if (sm_is_err(ret)) return ret; } /* XXX WARNING: changes key inplace! */ if (SM_IS_FLAG(flags, SMMAP_FL_LWR_KEY)) sm_str2lower(key); r = 0; #if MTA_USE_PTHREADS && HAVE_GETPWNAM_R # if POSIX_GETPWNAM_R r = getpwnam_r((const char *) sm_str_getdata(key), &pwentb, buf, sizeof(buf), &pwent); # else pwent = getpwnam_r((const char *) sm_str_getdata(key), &pwentb, buf, sizeof(buf)); # endif #else /* MTA_USE_PTHREADS && HAVE_GETPWNAM_R */ pwent = getpwnam((const char *) sm_str_getdata(key)); #endif /* MTA_USE_PTHREADS && HAVE_GETPWNAM_R */ ret = (pwent == NULL || r != 0) ? sm_error_perm(SM_EM_MAP, SM_E_NOTFOUND) : SM_SUCCESS; if (ret == SM_SUCCESS && data != NULL) { /* WARNING: must be NUL terminated string! */ ret = sm_str_scat(data, (const char *) pwent->pw_gecos); if (sm_is_err(ret)) return ret; } return ret; } #if 0 /* ** SM_PASSWD_ADD -- add key/data to PASSWD ** ** Parameters: ** map -- map context ** key -- key ** data -- data ** flags -- flags ** ** Returns: ** usual sm_error code */ static sm_ret_T sm_passwd_add(sm_map_P map, sm_map_key_P key, sm_map_data_P data, uint flags) { return sm_error_perm(SM_EM_MAP, EINVAL); } /* ** SM_PASSWD_RM -- remove key/data from PASSWD ** ** Parameters: ** map -- map context ** key -- key ** ** Returns: ** usual sm_error code */ static sm_ret_T sm_passwd_rm(sm_map_P map, sm_map_key_P key) { return sm_error_perm(SM_EM_MAP, EINVAL); } #endif /* 0 */ /* ** SM_PASSWD_CLASS_CREATE -- create PASSWD map class ** ** Parameters: ** maps -- map system context ** ** Returns: ** usual sm_error code */ sm_ret_T sm_passwd_class_create(sm_maps_P maps) { sm_ret_T ret; sm_mapc_P mapc; sm_cstr_P htype; #define PASSWD_TYPE "passwd" ret = SM_SUCCESS; mapc = NULL; htype = sm_cstr_scpyn0((const uchar *)PASSWD_TYPE, strlen(PASSWD_TYPE)); if (htype == NULL) goto error; /* is getpasswd() thread safe? */ ret = sm_mapc_create(maps, htype, #if MTA_USE_PTHREADS && HAVE_GETPWNAM_R 0, #else SMMAPC_FL_LCK_FULL, #endif sm_passwd_create, sm_passwd_open, sm_passwd_close, NULL, /* reopen XXX FIX! */ NULL, /* destroy */ NULL /*sm_passwd_add*/, NULL /*sm_passwd_rm*/, sm_passwd_alloc, sm_passwd_free, sm_passwd_lookup, sm_passwd_locate, sm_passwd_first, sm_passwd_next, sm_passwd_setopt, sm_passwd_getopt, &mapc); SM_CSTR_FREE(htype); return ret; error: if (ret == SM_SUCCESS) ret = sm_error_temp(SM_EM_MAP, ENOMEM); /* cleanup mapc? */ return ret; }