1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers. 3*7c478bd9Sstevel@tonic-gate * All rights reserved. 4*7c478bd9Sstevel@tonic-gate * 5*7c478bd9Sstevel@tonic-gate * By using this file, you agree to the terms and conditions set 6*7c478bd9Sstevel@tonic-gate * forth in the LICENSE file which can be found at the top level of 7*7c478bd9Sstevel@tonic-gate * the sendmail distribution. 8*7c478bd9Sstevel@tonic-gate */ 9*7c478bd9Sstevel@tonic-gate 10*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 11*7c478bd9Sstevel@tonic-gate 12*7c478bd9Sstevel@tonic-gate #include <sm/gen.h> 13*7c478bd9Sstevel@tonic-gate SM_RCSID("@(#)$Id: mbdb.c,v 1.40 2003/12/10 03:19:07 gshapiro Exp $") 14*7c478bd9Sstevel@tonic-gate 15*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 16*7c478bd9Sstevel@tonic-gate 17*7c478bd9Sstevel@tonic-gate #include <ctype.h> 18*7c478bd9Sstevel@tonic-gate #include <errno.h> 19*7c478bd9Sstevel@tonic-gate #include <pwd.h> 20*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 21*7c478bd9Sstevel@tonic-gate #include <setjmp.h> 22*7c478bd9Sstevel@tonic-gate #include <unistd.h> 23*7c478bd9Sstevel@tonic-gate 24*7c478bd9Sstevel@tonic-gate #include <sm/limits.h> 25*7c478bd9Sstevel@tonic-gate #include <sm/conf.h> 26*7c478bd9Sstevel@tonic-gate #include <sm/assert.h> 27*7c478bd9Sstevel@tonic-gate #include <sm/bitops.h> 28*7c478bd9Sstevel@tonic-gate #include <sm/errstring.h> 29*7c478bd9Sstevel@tonic-gate #include <sm/heap.h> 30*7c478bd9Sstevel@tonic-gate #include <sm/mbdb.h> 31*7c478bd9Sstevel@tonic-gate #include <sm/string.h> 32*7c478bd9Sstevel@tonic-gate # ifdef EX_OK 33*7c478bd9Sstevel@tonic-gate # undef EX_OK /* for SVr4.2 SMP */ 34*7c478bd9Sstevel@tonic-gate # endif /* EX_OK */ 35*7c478bd9Sstevel@tonic-gate #include <sm/sysexits.h> 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #if LDAPMAP 38*7c478bd9Sstevel@tonic-gate # if _LDAP_EXAMPLE_ 39*7c478bd9Sstevel@tonic-gate # include <sm/ldap.h> 40*7c478bd9Sstevel@tonic-gate # endif /* _LDAP_EXAMPLE_ */ 41*7c478bd9Sstevel@tonic-gate #endif /* LDAPMAP */ 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate typedef struct 44*7c478bd9Sstevel@tonic-gate { 45*7c478bd9Sstevel@tonic-gate char *mbdb_typename; 46*7c478bd9Sstevel@tonic-gate int (*mbdb_initialize) __P((char *)); 47*7c478bd9Sstevel@tonic-gate int (*mbdb_lookup) __P((char *name, SM_MBDB_T *user)); 48*7c478bd9Sstevel@tonic-gate void (*mbdb_terminate) __P((void)); 49*7c478bd9Sstevel@tonic-gate } SM_MBDB_TYPE_T; 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate static int mbdb_pw_initialize __P((char *)); 52*7c478bd9Sstevel@tonic-gate static int mbdb_pw_lookup __P((char *name, SM_MBDB_T *user)); 53*7c478bd9Sstevel@tonic-gate static void mbdb_pw_terminate __P((void)); 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate #if LDAPMAP 56*7c478bd9Sstevel@tonic-gate # if _LDAP_EXAMPLE_ 57*7c478bd9Sstevel@tonic-gate static struct sm_ldap_struct LDAPLMAP; 58*7c478bd9Sstevel@tonic-gate static int mbdb_ldap_initialize __P((char *)); 59*7c478bd9Sstevel@tonic-gate static int mbdb_ldap_lookup __P((char *name, SM_MBDB_T *user)); 60*7c478bd9Sstevel@tonic-gate static void mbdb_ldap_terminate __P((void)); 61*7c478bd9Sstevel@tonic-gate # endif /* _LDAP_EXAMPLE_ */ 62*7c478bd9Sstevel@tonic-gate #endif /* LDAPMAP */ 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate static SM_MBDB_TYPE_T SmMbdbTypes[] = 65*7c478bd9Sstevel@tonic-gate { 66*7c478bd9Sstevel@tonic-gate { "pw", mbdb_pw_initialize, mbdb_pw_lookup, mbdb_pw_terminate }, 67*7c478bd9Sstevel@tonic-gate #if LDAPMAP 68*7c478bd9Sstevel@tonic-gate # if _LDAP_EXAMPLE_ 69*7c478bd9Sstevel@tonic-gate { "ldap", mbdb_ldap_initialize, mbdb_ldap_lookup, mbdb_ldap_terminate }, 70*7c478bd9Sstevel@tonic-gate # endif /* _LDAP_EXAMPLE_ */ 71*7c478bd9Sstevel@tonic-gate #endif /* LDAPMAP */ 72*7c478bd9Sstevel@tonic-gate { NULL, NULL, NULL, NULL } 73*7c478bd9Sstevel@tonic-gate }; 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate static SM_MBDB_TYPE_T *SmMbdbType = &SmMbdbTypes[0]; 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate /* 78*7c478bd9Sstevel@tonic-gate ** SM_MBDB_INITIALIZE -- specify which mailbox database to use 79*7c478bd9Sstevel@tonic-gate ** 80*7c478bd9Sstevel@tonic-gate ** If this function is not called, then the "pw" implementation 81*7c478bd9Sstevel@tonic-gate ** is used by default; this implementation uses getpwnam(). 82*7c478bd9Sstevel@tonic-gate ** 83*7c478bd9Sstevel@tonic-gate ** Parameters: 84*7c478bd9Sstevel@tonic-gate ** mbdb -- Which mailbox database to use. 85*7c478bd9Sstevel@tonic-gate ** The argument has the form "name" or "name.arg". 86*7c478bd9Sstevel@tonic-gate ** "pw" means use getpwnam(). 87*7c478bd9Sstevel@tonic-gate ** 88*7c478bd9Sstevel@tonic-gate ** Results: 89*7c478bd9Sstevel@tonic-gate ** EX_OK on success, or an EX_* code on failure. 90*7c478bd9Sstevel@tonic-gate */ 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate int 93*7c478bd9Sstevel@tonic-gate sm_mbdb_initialize(mbdb) 94*7c478bd9Sstevel@tonic-gate char *mbdb; 95*7c478bd9Sstevel@tonic-gate { 96*7c478bd9Sstevel@tonic-gate size_t namelen; 97*7c478bd9Sstevel@tonic-gate int err; 98*7c478bd9Sstevel@tonic-gate char *name; 99*7c478bd9Sstevel@tonic-gate char *arg; 100*7c478bd9Sstevel@tonic-gate SM_MBDB_TYPE_T *t; 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate SM_REQUIRE(mbdb != NULL); 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate name = mbdb; 105*7c478bd9Sstevel@tonic-gate arg = strchr(mbdb, '.'); 106*7c478bd9Sstevel@tonic-gate if (arg == NULL) 107*7c478bd9Sstevel@tonic-gate namelen = strlen(name); 108*7c478bd9Sstevel@tonic-gate else 109*7c478bd9Sstevel@tonic-gate { 110*7c478bd9Sstevel@tonic-gate namelen = arg - name; 111*7c478bd9Sstevel@tonic-gate ++arg; 112*7c478bd9Sstevel@tonic-gate } 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate for (t = SmMbdbTypes; t->mbdb_typename != NULL; ++t) 115*7c478bd9Sstevel@tonic-gate { 116*7c478bd9Sstevel@tonic-gate if (strlen(t->mbdb_typename) == namelen && 117*7c478bd9Sstevel@tonic-gate strncmp(name, t->mbdb_typename, namelen) == 0) 118*7c478bd9Sstevel@tonic-gate { 119*7c478bd9Sstevel@tonic-gate err = EX_OK; 120*7c478bd9Sstevel@tonic-gate if (t->mbdb_initialize != NULL) 121*7c478bd9Sstevel@tonic-gate err = t->mbdb_initialize(arg); 122*7c478bd9Sstevel@tonic-gate if (err == EX_OK) 123*7c478bd9Sstevel@tonic-gate SmMbdbType = t; 124*7c478bd9Sstevel@tonic-gate return err; 125*7c478bd9Sstevel@tonic-gate } 126*7c478bd9Sstevel@tonic-gate } 127*7c478bd9Sstevel@tonic-gate return EX_UNAVAILABLE; 128*7c478bd9Sstevel@tonic-gate } 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate /* 131*7c478bd9Sstevel@tonic-gate ** SM_MBDB_TERMINATE -- terminate connection to the mailbox database 132*7c478bd9Sstevel@tonic-gate ** 133*7c478bd9Sstevel@tonic-gate ** Because this function closes any cached file descriptors that 134*7c478bd9Sstevel@tonic-gate ** are being held open for the connection to the mailbox database, 135*7c478bd9Sstevel@tonic-gate ** it should be called for security reasons prior to dropping privileges 136*7c478bd9Sstevel@tonic-gate ** and execing another process. 137*7c478bd9Sstevel@tonic-gate ** 138*7c478bd9Sstevel@tonic-gate ** Parameters: 139*7c478bd9Sstevel@tonic-gate ** none. 140*7c478bd9Sstevel@tonic-gate ** 141*7c478bd9Sstevel@tonic-gate ** Results: 142*7c478bd9Sstevel@tonic-gate ** none. 143*7c478bd9Sstevel@tonic-gate */ 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate void 146*7c478bd9Sstevel@tonic-gate sm_mbdb_terminate() 147*7c478bd9Sstevel@tonic-gate { 148*7c478bd9Sstevel@tonic-gate if (SmMbdbType->mbdb_terminate != NULL) 149*7c478bd9Sstevel@tonic-gate SmMbdbType->mbdb_terminate(); 150*7c478bd9Sstevel@tonic-gate } 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate /* 153*7c478bd9Sstevel@tonic-gate ** SM_MBDB_LOOKUP -- look up a local mail recipient, given name 154*7c478bd9Sstevel@tonic-gate ** 155*7c478bd9Sstevel@tonic-gate ** Parameters: 156*7c478bd9Sstevel@tonic-gate ** name -- name of local mail recipient 157*7c478bd9Sstevel@tonic-gate ** user -- pointer to structure to fill in on success 158*7c478bd9Sstevel@tonic-gate ** 159*7c478bd9Sstevel@tonic-gate ** Results: 160*7c478bd9Sstevel@tonic-gate ** On success, fill in *user and return EX_OK. 161*7c478bd9Sstevel@tonic-gate ** If the user does not exist, return EX_NOUSER. 162*7c478bd9Sstevel@tonic-gate ** If a temporary failure (eg, a network failure) occurred, 163*7c478bd9Sstevel@tonic-gate ** return EX_TEMPFAIL. Otherwise return EX_OSERR. 164*7c478bd9Sstevel@tonic-gate */ 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate int 167*7c478bd9Sstevel@tonic-gate sm_mbdb_lookup(name, user) 168*7c478bd9Sstevel@tonic-gate char *name; 169*7c478bd9Sstevel@tonic-gate SM_MBDB_T *user; 170*7c478bd9Sstevel@tonic-gate { 171*7c478bd9Sstevel@tonic-gate int ret = EX_NOUSER; 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate if (SmMbdbType->mbdb_lookup != NULL) 174*7c478bd9Sstevel@tonic-gate ret = SmMbdbType->mbdb_lookup(name, user); 175*7c478bd9Sstevel@tonic-gate return ret; 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate /* 179*7c478bd9Sstevel@tonic-gate ** SM_MBDB_FROMPW -- copy from struct pw to SM_MBDB_T 180*7c478bd9Sstevel@tonic-gate ** 181*7c478bd9Sstevel@tonic-gate ** Parameters: 182*7c478bd9Sstevel@tonic-gate ** user -- destination user information structure 183*7c478bd9Sstevel@tonic-gate ** pw -- source passwd structure 184*7c478bd9Sstevel@tonic-gate ** 185*7c478bd9Sstevel@tonic-gate ** Results: 186*7c478bd9Sstevel@tonic-gate ** none. 187*7c478bd9Sstevel@tonic-gate */ 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate void 190*7c478bd9Sstevel@tonic-gate sm_mbdb_frompw(user, pw) 191*7c478bd9Sstevel@tonic-gate SM_MBDB_T *user; 192*7c478bd9Sstevel@tonic-gate struct passwd *pw; 193*7c478bd9Sstevel@tonic-gate { 194*7c478bd9Sstevel@tonic-gate SM_REQUIRE(user != NULL); 195*7c478bd9Sstevel@tonic-gate (void) sm_strlcpy(user->mbdb_name, pw->pw_name, 196*7c478bd9Sstevel@tonic-gate sizeof(user->mbdb_name)); 197*7c478bd9Sstevel@tonic-gate user->mbdb_uid = pw->pw_uid; 198*7c478bd9Sstevel@tonic-gate user->mbdb_gid = pw->pw_gid; 199*7c478bd9Sstevel@tonic-gate sm_pwfullname(pw->pw_gecos, pw->pw_name, user->mbdb_fullname, 200*7c478bd9Sstevel@tonic-gate sizeof(user->mbdb_fullname)); 201*7c478bd9Sstevel@tonic-gate (void) sm_strlcpy(user->mbdb_homedir, pw->pw_dir, 202*7c478bd9Sstevel@tonic-gate sizeof(user->mbdb_homedir)); 203*7c478bd9Sstevel@tonic-gate (void) sm_strlcpy(user->mbdb_shell, pw->pw_shell, 204*7c478bd9Sstevel@tonic-gate sizeof(user->mbdb_shell)); 205*7c478bd9Sstevel@tonic-gate } 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate /* 208*7c478bd9Sstevel@tonic-gate ** SM_PWFULLNAME -- build full name of user from pw_gecos field. 209*7c478bd9Sstevel@tonic-gate ** 210*7c478bd9Sstevel@tonic-gate ** This routine interprets the strange entry that would appear 211*7c478bd9Sstevel@tonic-gate ** in the GECOS field of the password file. 212*7c478bd9Sstevel@tonic-gate ** 213*7c478bd9Sstevel@tonic-gate ** Parameters: 214*7c478bd9Sstevel@tonic-gate ** gecos -- name to build. 215*7c478bd9Sstevel@tonic-gate ** user -- the login name of this user (for &). 216*7c478bd9Sstevel@tonic-gate ** buf -- place to put the result. 217*7c478bd9Sstevel@tonic-gate ** buflen -- length of buf. 218*7c478bd9Sstevel@tonic-gate ** 219*7c478bd9Sstevel@tonic-gate ** Returns: 220*7c478bd9Sstevel@tonic-gate ** none. 221*7c478bd9Sstevel@tonic-gate */ 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate #if _FFR_HANDLE_ISO8859_GECOS 224*7c478bd9Sstevel@tonic-gate static char Latin1ToASCII[128] = 225*7c478bd9Sstevel@tonic-gate { 226*7c478bd9Sstevel@tonic-gate 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 227*7c478bd9Sstevel@tonic-gate 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 228*7c478bd9Sstevel@tonic-gate 99, 80, 36, 89, 124, 36, 34, 99, 97, 60, 45, 45, 114, 45, 111, 42, 229*7c478bd9Sstevel@tonic-gate 50, 51, 39, 117, 80, 46, 44, 49, 111, 62, 42, 42, 42, 63, 65, 65, 230*7c478bd9Sstevel@tonic-gate 65, 65, 65, 65, 65, 67, 69, 69, 69, 69, 73, 73, 73, 73, 68, 78, 79, 231*7c478bd9Sstevel@tonic-gate 79, 79, 79, 79, 88, 79, 85, 85, 85, 85, 89, 80, 66, 97, 97, 97, 97, 232*7c478bd9Sstevel@tonic-gate 97, 97, 97, 99, 101, 101, 101, 101, 105, 105, 105, 105, 100, 110, 233*7c478bd9Sstevel@tonic-gate 111, 111, 111, 111, 111, 47, 111, 117, 117, 117, 117, 121, 112, 121 234*7c478bd9Sstevel@tonic-gate }; 235*7c478bd9Sstevel@tonic-gate #endif /* _FFR_HANDLE_ISO8859_GECOS */ 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate void 238*7c478bd9Sstevel@tonic-gate sm_pwfullname(gecos, user, buf, buflen) 239*7c478bd9Sstevel@tonic-gate register char *gecos; 240*7c478bd9Sstevel@tonic-gate char *user; 241*7c478bd9Sstevel@tonic-gate char *buf; 242*7c478bd9Sstevel@tonic-gate size_t buflen; 243*7c478bd9Sstevel@tonic-gate { 244*7c478bd9Sstevel@tonic-gate register char *p; 245*7c478bd9Sstevel@tonic-gate register char *bp = buf; 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate if (*gecos == '*') 248*7c478bd9Sstevel@tonic-gate gecos++; 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate /* copy gecos, interpolating & to be full name */ 251*7c478bd9Sstevel@tonic-gate for (p = gecos; *p != '\0' && *p != ',' && *p != ';' && *p != '%'; p++) 252*7c478bd9Sstevel@tonic-gate { 253*7c478bd9Sstevel@tonic-gate if (bp >= &buf[buflen - 1]) 254*7c478bd9Sstevel@tonic-gate { 255*7c478bd9Sstevel@tonic-gate /* buffer overflow -- just use login name */ 256*7c478bd9Sstevel@tonic-gate (void) sm_strlcpy(buf, user, buflen); 257*7c478bd9Sstevel@tonic-gate return; 258*7c478bd9Sstevel@tonic-gate } 259*7c478bd9Sstevel@tonic-gate if (*p == '&') 260*7c478bd9Sstevel@tonic-gate { 261*7c478bd9Sstevel@tonic-gate /* interpolate full name */ 262*7c478bd9Sstevel@tonic-gate (void) sm_strlcpy(bp, user, buflen - (bp - buf)); 263*7c478bd9Sstevel@tonic-gate *bp = toupper(*bp); 264*7c478bd9Sstevel@tonic-gate bp += strlen(bp); 265*7c478bd9Sstevel@tonic-gate } 266*7c478bd9Sstevel@tonic-gate else 267*7c478bd9Sstevel@tonic-gate { 268*7c478bd9Sstevel@tonic-gate #if _FFR_HANDLE_ISO8859_GECOS 269*7c478bd9Sstevel@tonic-gate if ((unsigned char) *p >= 128) 270*7c478bd9Sstevel@tonic-gate *bp++ = Latin1ToASCII[(unsigned char) *p - 128]; 271*7c478bd9Sstevel@tonic-gate else 272*7c478bd9Sstevel@tonic-gate #endif /* _FFR_HANDLE_ISO8859_GECOS */ 273*7c478bd9Sstevel@tonic-gate *bp++ = *p; 274*7c478bd9Sstevel@tonic-gate } 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate *bp = '\0'; 277*7c478bd9Sstevel@tonic-gate } 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate /* 280*7c478bd9Sstevel@tonic-gate ** /etc/passwd implementation. 281*7c478bd9Sstevel@tonic-gate */ 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate /* 284*7c478bd9Sstevel@tonic-gate ** MBDB_PW_INITIALIZE -- initialize getpwnam() version 285*7c478bd9Sstevel@tonic-gate ** 286*7c478bd9Sstevel@tonic-gate ** Parameters: 287*7c478bd9Sstevel@tonic-gate ** arg -- unused. 288*7c478bd9Sstevel@tonic-gate ** 289*7c478bd9Sstevel@tonic-gate ** Results: 290*7c478bd9Sstevel@tonic-gate ** EX_OK. 291*7c478bd9Sstevel@tonic-gate */ 292*7c478bd9Sstevel@tonic-gate 293*7c478bd9Sstevel@tonic-gate /* ARGSUSED0 */ 294*7c478bd9Sstevel@tonic-gate static int 295*7c478bd9Sstevel@tonic-gate mbdb_pw_initialize(arg) 296*7c478bd9Sstevel@tonic-gate char *arg; 297*7c478bd9Sstevel@tonic-gate { 298*7c478bd9Sstevel@tonic-gate return EX_OK; 299*7c478bd9Sstevel@tonic-gate } 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate /* 302*7c478bd9Sstevel@tonic-gate ** MBDB_PW_LOOKUP -- look up a local mail recipient, given name 303*7c478bd9Sstevel@tonic-gate ** 304*7c478bd9Sstevel@tonic-gate ** Parameters: 305*7c478bd9Sstevel@tonic-gate ** name -- name of local mail recipient 306*7c478bd9Sstevel@tonic-gate ** user -- pointer to structure to fill in on success 307*7c478bd9Sstevel@tonic-gate ** 308*7c478bd9Sstevel@tonic-gate ** Results: 309*7c478bd9Sstevel@tonic-gate ** On success, fill in *user and return EX_OK. 310*7c478bd9Sstevel@tonic-gate ** Failure: EX_NOUSER. 311*7c478bd9Sstevel@tonic-gate */ 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate static int 314*7c478bd9Sstevel@tonic-gate mbdb_pw_lookup(name, user) 315*7c478bd9Sstevel@tonic-gate char *name; 316*7c478bd9Sstevel@tonic-gate SM_MBDB_T *user; 317*7c478bd9Sstevel@tonic-gate { 318*7c478bd9Sstevel@tonic-gate struct passwd *pw; 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate #ifdef HESIOD 321*7c478bd9Sstevel@tonic-gate /* DEC Hesiod getpwnam accepts numeric strings -- short circuit it */ 322*7c478bd9Sstevel@tonic-gate { 323*7c478bd9Sstevel@tonic-gate char *p; 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate for (p = name; *p != '\0'; p++) 326*7c478bd9Sstevel@tonic-gate if (!isascii(*p) || !isdigit(*p)) 327*7c478bd9Sstevel@tonic-gate break; 328*7c478bd9Sstevel@tonic-gate if (*p == '\0') 329*7c478bd9Sstevel@tonic-gate return EX_NOUSER; 330*7c478bd9Sstevel@tonic-gate } 331*7c478bd9Sstevel@tonic-gate #endif /* HESIOD */ 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate errno = 0; 334*7c478bd9Sstevel@tonic-gate pw = getpwnam(name); 335*7c478bd9Sstevel@tonic-gate if (pw == NULL) 336*7c478bd9Sstevel@tonic-gate { 337*7c478bd9Sstevel@tonic-gate #if 0 338*7c478bd9Sstevel@tonic-gate /* 339*7c478bd9Sstevel@tonic-gate ** getpwnam() isn't advertised as setting errno. 340*7c478bd9Sstevel@tonic-gate ** In fact, under FreeBSD, non-root getpwnam() on 341*7c478bd9Sstevel@tonic-gate ** non-existant users returns NULL with errno = EPERM. 342*7c478bd9Sstevel@tonic-gate ** This test won't work. 343*7c478bd9Sstevel@tonic-gate */ 344*7c478bd9Sstevel@tonic-gate switch (errno) 345*7c478bd9Sstevel@tonic-gate { 346*7c478bd9Sstevel@tonic-gate case 0: 347*7c478bd9Sstevel@tonic-gate return EX_NOUSER; 348*7c478bd9Sstevel@tonic-gate case EIO: 349*7c478bd9Sstevel@tonic-gate return EX_OSERR; 350*7c478bd9Sstevel@tonic-gate default: 351*7c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate #endif /* 0 */ 354*7c478bd9Sstevel@tonic-gate return EX_NOUSER; 355*7c478bd9Sstevel@tonic-gate } 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate sm_mbdb_frompw(user, pw); 358*7c478bd9Sstevel@tonic-gate return EX_OK; 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate /* 362*7c478bd9Sstevel@tonic-gate ** MBDB_PW_TERMINATE -- terminate connection to the mailbox database 363*7c478bd9Sstevel@tonic-gate ** 364*7c478bd9Sstevel@tonic-gate ** Parameters: 365*7c478bd9Sstevel@tonic-gate ** none. 366*7c478bd9Sstevel@tonic-gate ** 367*7c478bd9Sstevel@tonic-gate ** Results: 368*7c478bd9Sstevel@tonic-gate ** none. 369*7c478bd9Sstevel@tonic-gate */ 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate static void 372*7c478bd9Sstevel@tonic-gate mbdb_pw_terminate() 373*7c478bd9Sstevel@tonic-gate { 374*7c478bd9Sstevel@tonic-gate endpwent(); 375*7c478bd9Sstevel@tonic-gate } 376*7c478bd9Sstevel@tonic-gate 377*7c478bd9Sstevel@tonic-gate #if LDAPMAP 378*7c478bd9Sstevel@tonic-gate # if _LDAP_EXAMPLE_ 379*7c478bd9Sstevel@tonic-gate /* 380*7c478bd9Sstevel@tonic-gate ** LDAP example implementation based on RFC 2307, "An Approach for Using 381*7c478bd9Sstevel@tonic-gate ** LDAP as a Network Information Service": 382*7c478bd9Sstevel@tonic-gate ** 383*7c478bd9Sstevel@tonic-gate ** ( nisSchema.1.0 NAME 'uidNumber' 384*7c478bd9Sstevel@tonic-gate ** DESC 'An integer uniquely identifying a user in an 385*7c478bd9Sstevel@tonic-gate ** administrative domain' 386*7c478bd9Sstevel@tonic-gate ** EQUALITY integerMatch SYNTAX 'INTEGER' SINGLE-VALUE ) 387*7c478bd9Sstevel@tonic-gate ** 388*7c478bd9Sstevel@tonic-gate ** ( nisSchema.1.1 NAME 'gidNumber' 389*7c478bd9Sstevel@tonic-gate ** DESC 'An integer uniquely identifying a group in an 390*7c478bd9Sstevel@tonic-gate ** administrative domain' 391*7c478bd9Sstevel@tonic-gate ** EQUALITY integerMatch SYNTAX 'INTEGER' SINGLE-VALUE ) 392*7c478bd9Sstevel@tonic-gate ** 393*7c478bd9Sstevel@tonic-gate ** ( nisSchema.1.2 NAME 'gecos' 394*7c478bd9Sstevel@tonic-gate ** DESC 'The GECOS field; the common name' 395*7c478bd9Sstevel@tonic-gate ** EQUALITY caseIgnoreIA5Match 396*7c478bd9Sstevel@tonic-gate ** SUBSTRINGS caseIgnoreIA5SubstringsMatch 397*7c478bd9Sstevel@tonic-gate ** SYNTAX 'IA5String' SINGLE-VALUE ) 398*7c478bd9Sstevel@tonic-gate ** 399*7c478bd9Sstevel@tonic-gate ** ( nisSchema.1.3 NAME 'homeDirectory' 400*7c478bd9Sstevel@tonic-gate ** DESC 'The absolute path to the home directory' 401*7c478bd9Sstevel@tonic-gate ** EQUALITY caseExactIA5Match 402*7c478bd9Sstevel@tonic-gate ** SYNTAX 'IA5String' SINGLE-VALUE ) 403*7c478bd9Sstevel@tonic-gate ** 404*7c478bd9Sstevel@tonic-gate ** ( nisSchema.1.4 NAME 'loginShell' 405*7c478bd9Sstevel@tonic-gate ** DESC 'The path to the login shell' 406*7c478bd9Sstevel@tonic-gate ** EQUALITY caseExactIA5Match 407*7c478bd9Sstevel@tonic-gate ** SYNTAX 'IA5String' SINGLE-VALUE ) 408*7c478bd9Sstevel@tonic-gate ** 409*7c478bd9Sstevel@tonic-gate ** ( nisSchema.2.0 NAME 'posixAccount' SUP top AUXILIARY 410*7c478bd9Sstevel@tonic-gate ** DESC 'Abstraction of an account with POSIX attributes' 411*7c478bd9Sstevel@tonic-gate ** MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory ) 412*7c478bd9Sstevel@tonic-gate ** MAY ( userPassword $ loginShell $ gecos $ description ) ) 413*7c478bd9Sstevel@tonic-gate ** 414*7c478bd9Sstevel@tonic-gate */ 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate # define MBDB_LDAP_LABEL "MailboxDatabase" 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate # ifndef MBDB_LDAP_FILTER 419*7c478bd9Sstevel@tonic-gate # define MBDB_LDAP_FILTER "(&(objectClass=posixAccount)(uid=%0))" 420*7c478bd9Sstevel@tonic-gate # endif /* MBDB_LDAP_FILTER */ 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate # ifndef MBDB_DEFAULT_LDAP_BASEDN 423*7c478bd9Sstevel@tonic-gate # define MBDB_DEFAULT_LDAP_BASEDN NULL 424*7c478bd9Sstevel@tonic-gate # endif /* MBDB_DEFAULT_LDAP_BASEDN */ 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate # ifndef MBDB_DEFAULT_LDAP_SERVER 427*7c478bd9Sstevel@tonic-gate # define MBDB_DEFAULT_LDAP_SERVER NULL 428*7c478bd9Sstevel@tonic-gate # endif /* MBDB_DEFAULT_LDAP_SERVER */ 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate /* 431*7c478bd9Sstevel@tonic-gate ** MBDB_LDAP_INITIALIZE -- initialize LDAP version 432*7c478bd9Sstevel@tonic-gate ** 433*7c478bd9Sstevel@tonic-gate ** Parameters: 434*7c478bd9Sstevel@tonic-gate ** arg -- LDAP specification 435*7c478bd9Sstevel@tonic-gate ** 436*7c478bd9Sstevel@tonic-gate ** Results: 437*7c478bd9Sstevel@tonic-gate ** EX_OK on success, or an EX_* code on failure. 438*7c478bd9Sstevel@tonic-gate */ 439*7c478bd9Sstevel@tonic-gate 440*7c478bd9Sstevel@tonic-gate static int 441*7c478bd9Sstevel@tonic-gate mbdb_ldap_initialize(arg) 442*7c478bd9Sstevel@tonic-gate char *arg; 443*7c478bd9Sstevel@tonic-gate { 444*7c478bd9Sstevel@tonic-gate sm_ldap_clear(&LDAPLMAP); 445*7c478bd9Sstevel@tonic-gate LDAPLMAP.ldap_base = MBDB_DEFAULT_LDAP_BASEDN; 446*7c478bd9Sstevel@tonic-gate LDAPLMAP.ldap_host = MBDB_DEFAULT_LDAP_SERVER; 447*7c478bd9Sstevel@tonic-gate LDAPLMAP.ldap_filter = MBDB_LDAP_FILTER; 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate /* Only want one match */ 450*7c478bd9Sstevel@tonic-gate LDAPLMAP.ldap_sizelimit = 1; 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate /* interpolate new ldap_base and ldap_host from arg if given */ 453*7c478bd9Sstevel@tonic-gate if (arg != NULL && *arg != '\0') 454*7c478bd9Sstevel@tonic-gate { 455*7c478bd9Sstevel@tonic-gate char *new; 456*7c478bd9Sstevel@tonic-gate char *sep; 457*7c478bd9Sstevel@tonic-gate size_t len; 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate len = strlen(arg) + 1; 460*7c478bd9Sstevel@tonic-gate new = sm_malloc(len); 461*7c478bd9Sstevel@tonic-gate if (new == NULL) 462*7c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 463*7c478bd9Sstevel@tonic-gate (void) sm_strlcpy(new, arg, len); 464*7c478bd9Sstevel@tonic-gate sep = strrchr(new, '@'); 465*7c478bd9Sstevel@tonic-gate if (sep != NULL) 466*7c478bd9Sstevel@tonic-gate { 467*7c478bd9Sstevel@tonic-gate *sep++ = '\0'; 468*7c478bd9Sstevel@tonic-gate LDAPLMAP.ldap_host = sep; 469*7c478bd9Sstevel@tonic-gate } 470*7c478bd9Sstevel@tonic-gate LDAPLMAP.ldap_base = new; 471*7c478bd9Sstevel@tonic-gate } 472*7c478bd9Sstevel@tonic-gate return EX_OK; 473*7c478bd9Sstevel@tonic-gate } 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate 476*7c478bd9Sstevel@tonic-gate /* 477*7c478bd9Sstevel@tonic-gate ** MBDB_LDAP_LOOKUP -- look up a local mail recipient, given name 478*7c478bd9Sstevel@tonic-gate ** 479*7c478bd9Sstevel@tonic-gate ** Parameters: 480*7c478bd9Sstevel@tonic-gate ** name -- name of local mail recipient 481*7c478bd9Sstevel@tonic-gate ** user -- pointer to structure to fill in on success 482*7c478bd9Sstevel@tonic-gate ** 483*7c478bd9Sstevel@tonic-gate ** Results: 484*7c478bd9Sstevel@tonic-gate ** On success, fill in *user and return EX_OK. 485*7c478bd9Sstevel@tonic-gate ** Failure: EX_NOUSER. 486*7c478bd9Sstevel@tonic-gate */ 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate #define NEED_FULLNAME 0x01 489*7c478bd9Sstevel@tonic-gate #define NEED_HOMEDIR 0x02 490*7c478bd9Sstevel@tonic-gate #define NEED_SHELL 0x04 491*7c478bd9Sstevel@tonic-gate #define NEED_UID 0x08 492*7c478bd9Sstevel@tonic-gate #define NEED_GID 0x10 493*7c478bd9Sstevel@tonic-gate 494*7c478bd9Sstevel@tonic-gate static int 495*7c478bd9Sstevel@tonic-gate mbdb_ldap_lookup(name, user) 496*7c478bd9Sstevel@tonic-gate char *name; 497*7c478bd9Sstevel@tonic-gate SM_MBDB_T *user; 498*7c478bd9Sstevel@tonic-gate { 499*7c478bd9Sstevel@tonic-gate int msgid; 500*7c478bd9Sstevel@tonic-gate int need; 501*7c478bd9Sstevel@tonic-gate int ret; 502*7c478bd9Sstevel@tonic-gate int save_errno; 503*7c478bd9Sstevel@tonic-gate LDAPMessage *entry; 504*7c478bd9Sstevel@tonic-gate BerElement *ber; 505*7c478bd9Sstevel@tonic-gate char *attr = NULL; 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate if (strlen(name) >= sizeof(user->mbdb_name)) 508*7c478bd9Sstevel@tonic-gate { 509*7c478bd9Sstevel@tonic-gate errno = EINVAL; 510*7c478bd9Sstevel@tonic-gate return EX_NOUSER; 511*7c478bd9Sstevel@tonic-gate } 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate if (LDAPLMAP.ldap_filter == NULL) 514*7c478bd9Sstevel@tonic-gate { 515*7c478bd9Sstevel@tonic-gate /* map not initialized, but don't have arg here */ 516*7c478bd9Sstevel@tonic-gate errno = EFAULT; 517*7c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 518*7c478bd9Sstevel@tonic-gate } 519*7c478bd9Sstevel@tonic-gate 520*7c478bd9Sstevel@tonic-gate if (LDAPLMAP.ldap_pid != getpid()) 521*7c478bd9Sstevel@tonic-gate { 522*7c478bd9Sstevel@tonic-gate /* re-open map in this child process */ 523*7c478bd9Sstevel@tonic-gate LDAPLMAP.ldap_ld = NULL; 524*7c478bd9Sstevel@tonic-gate } 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate if (LDAPLMAP.ldap_ld == NULL) 527*7c478bd9Sstevel@tonic-gate { 528*7c478bd9Sstevel@tonic-gate /* map not open, try to open now */ 529*7c478bd9Sstevel@tonic-gate if (!sm_ldap_start(MBDB_LDAP_LABEL, &LDAPLMAP)) 530*7c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate 533*7c478bd9Sstevel@tonic-gate sm_ldap_setopts(LDAPLMAP.ldap_ld, &LDAPLMAP); 534*7c478bd9Sstevel@tonic-gate msgid = sm_ldap_search(&LDAPLMAP, name); 535*7c478bd9Sstevel@tonic-gate if (msgid == -1) 536*7c478bd9Sstevel@tonic-gate { 537*7c478bd9Sstevel@tonic-gate save_errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld) + E_LDAPBASE; 538*7c478bd9Sstevel@tonic-gate # ifdef LDAP_SERVER_DOWN 539*7c478bd9Sstevel@tonic-gate if (errno == LDAP_SERVER_DOWN) 540*7c478bd9Sstevel@tonic-gate { 541*7c478bd9Sstevel@tonic-gate /* server disappeared, try reopen on next search */ 542*7c478bd9Sstevel@tonic-gate sm_ldap_close(&LDAPLMAP); 543*7c478bd9Sstevel@tonic-gate } 544*7c478bd9Sstevel@tonic-gate # endif /* LDAP_SERVER_DOWN */ 545*7c478bd9Sstevel@tonic-gate errno = save_errno; 546*7c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 547*7c478bd9Sstevel@tonic-gate } 548*7c478bd9Sstevel@tonic-gate 549*7c478bd9Sstevel@tonic-gate /* Get results */ 550*7c478bd9Sstevel@tonic-gate ret = ldap_result(LDAPLMAP.ldap_ld, msgid, 1, 551*7c478bd9Sstevel@tonic-gate (LDAPLMAP.ldap_timeout.tv_sec == 0 ? NULL : 552*7c478bd9Sstevel@tonic-gate &(LDAPLMAP.ldap_timeout)), 553*7c478bd9Sstevel@tonic-gate &(LDAPLMAP.ldap_res)); 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate if (ret != LDAP_RES_SEARCH_RESULT && 556*7c478bd9Sstevel@tonic-gate ret != LDAP_RES_SEARCH_ENTRY) 557*7c478bd9Sstevel@tonic-gate { 558*7c478bd9Sstevel@tonic-gate if (ret == 0) 559*7c478bd9Sstevel@tonic-gate errno = ETIMEDOUT; 560*7c478bd9Sstevel@tonic-gate else 561*7c478bd9Sstevel@tonic-gate errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld); 562*7c478bd9Sstevel@tonic-gate ret = EX_TEMPFAIL; 563*7c478bd9Sstevel@tonic-gate goto abort; 564*7c478bd9Sstevel@tonic-gate } 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate entry = ldap_first_entry(LDAPLMAP.ldap_ld, LDAPLMAP.ldap_res); 567*7c478bd9Sstevel@tonic-gate if (entry == NULL) 568*7c478bd9Sstevel@tonic-gate { 569*7c478bd9Sstevel@tonic-gate save_errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld); 570*7c478bd9Sstevel@tonic-gate if (save_errno == LDAP_SUCCESS) 571*7c478bd9Sstevel@tonic-gate { 572*7c478bd9Sstevel@tonic-gate errno = ENOENT; 573*7c478bd9Sstevel@tonic-gate ret = EX_NOUSER; 574*7c478bd9Sstevel@tonic-gate } 575*7c478bd9Sstevel@tonic-gate else 576*7c478bd9Sstevel@tonic-gate { 577*7c478bd9Sstevel@tonic-gate errno = save_errno; 578*7c478bd9Sstevel@tonic-gate ret = EX_TEMPFAIL; 579*7c478bd9Sstevel@tonic-gate } 580*7c478bd9Sstevel@tonic-gate goto abort; 581*7c478bd9Sstevel@tonic-gate } 582*7c478bd9Sstevel@tonic-gate 583*7c478bd9Sstevel@tonic-gate # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 584*7c478bd9Sstevel@tonic-gate /* 585*7c478bd9Sstevel@tonic-gate ** Reset value to prevent lingering 586*7c478bd9Sstevel@tonic-gate ** LDAP_DECODING_ERROR due to 587*7c478bd9Sstevel@tonic-gate ** OpenLDAP 1.X's hack (see below) 588*7c478bd9Sstevel@tonic-gate */ 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate LDAPLMAP.ldap_ld->ld_errno = LDAP_SUCCESS; 591*7c478bd9Sstevel@tonic-gate # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate ret = EX_OK; 594*7c478bd9Sstevel@tonic-gate need = NEED_FULLNAME|NEED_HOMEDIR|NEED_SHELL|NEED_UID|NEED_GID; 595*7c478bd9Sstevel@tonic-gate for (attr = ldap_first_attribute(LDAPLMAP.ldap_ld, entry, &ber); 596*7c478bd9Sstevel@tonic-gate attr != NULL; 597*7c478bd9Sstevel@tonic-gate attr = ldap_next_attribute(LDAPLMAP.ldap_ld, entry, ber)) 598*7c478bd9Sstevel@tonic-gate { 599*7c478bd9Sstevel@tonic-gate char **vals; 600*7c478bd9Sstevel@tonic-gate 601*7c478bd9Sstevel@tonic-gate vals = ldap_get_values(LDAPLMAP.ldap_ld, entry, attr); 602*7c478bd9Sstevel@tonic-gate if (vals == NULL) 603*7c478bd9Sstevel@tonic-gate { 604*7c478bd9Sstevel@tonic-gate errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld); 605*7c478bd9Sstevel@tonic-gate if (errno == LDAP_SUCCESS) 606*7c478bd9Sstevel@tonic-gate { 607*7c478bd9Sstevel@tonic-gate ldap_memfree(attr); 608*7c478bd9Sstevel@tonic-gate continue; 609*7c478bd9Sstevel@tonic-gate } 610*7c478bd9Sstevel@tonic-gate 611*7c478bd9Sstevel@tonic-gate /* Must be an error */ 612*7c478bd9Sstevel@tonic-gate errno += E_LDAPBASE; 613*7c478bd9Sstevel@tonic-gate ret = EX_TEMPFAIL; 614*7c478bd9Sstevel@tonic-gate goto abort; 615*7c478bd9Sstevel@tonic-gate } 616*7c478bd9Sstevel@tonic-gate 617*7c478bd9Sstevel@tonic-gate # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) 618*7c478bd9Sstevel@tonic-gate /* 619*7c478bd9Sstevel@tonic-gate ** Reset value to prevent lingering 620*7c478bd9Sstevel@tonic-gate ** LDAP_DECODING_ERROR due to 621*7c478bd9Sstevel@tonic-gate ** OpenLDAP 1.X's hack (see below) 622*7c478bd9Sstevel@tonic-gate */ 623*7c478bd9Sstevel@tonic-gate 624*7c478bd9Sstevel@tonic-gate LDAPLMAP.ldap_ld->ld_errno = LDAP_SUCCESS; 625*7c478bd9Sstevel@tonic-gate # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ 626*7c478bd9Sstevel@tonic-gate 627*7c478bd9Sstevel@tonic-gate if (vals[0] == NULL || vals[0][0] == '\0') 628*7c478bd9Sstevel@tonic-gate goto skip; 629*7c478bd9Sstevel@tonic-gate 630*7c478bd9Sstevel@tonic-gate if (strcasecmp(attr, "gecos") == 0) 631*7c478bd9Sstevel@tonic-gate { 632*7c478bd9Sstevel@tonic-gate if (!bitset(NEED_FULLNAME, need) || 633*7c478bd9Sstevel@tonic-gate strlen(vals[0]) >= sizeof(user->mbdb_fullname)) 634*7c478bd9Sstevel@tonic-gate goto skip; 635*7c478bd9Sstevel@tonic-gate 636*7c478bd9Sstevel@tonic-gate sm_pwfullname(vals[0], name, user->mbdb_fullname, 637*7c478bd9Sstevel@tonic-gate sizeof(user->mbdb_fullname)); 638*7c478bd9Sstevel@tonic-gate need &= ~NEED_FULLNAME; 639*7c478bd9Sstevel@tonic-gate } 640*7c478bd9Sstevel@tonic-gate else if (strcasecmp(attr, "homeDirectory") == 0) 641*7c478bd9Sstevel@tonic-gate { 642*7c478bd9Sstevel@tonic-gate if (!bitset(NEED_HOMEDIR, need) || 643*7c478bd9Sstevel@tonic-gate strlen(vals[0]) >= sizeof(user->mbdb_homedir)) 644*7c478bd9Sstevel@tonic-gate goto skip; 645*7c478bd9Sstevel@tonic-gate 646*7c478bd9Sstevel@tonic-gate (void) sm_strlcpy(user->mbdb_homedir, vals[0], 647*7c478bd9Sstevel@tonic-gate sizeof(user->mbdb_homedir)); 648*7c478bd9Sstevel@tonic-gate need &= ~NEED_HOMEDIR; 649*7c478bd9Sstevel@tonic-gate } 650*7c478bd9Sstevel@tonic-gate else if (strcasecmp(attr, "loginShell") == 0) 651*7c478bd9Sstevel@tonic-gate { 652*7c478bd9Sstevel@tonic-gate if (!bitset(NEED_SHELL, need) || 653*7c478bd9Sstevel@tonic-gate strlen(vals[0]) >= sizeof(user->mbdb_shell)) 654*7c478bd9Sstevel@tonic-gate goto skip; 655*7c478bd9Sstevel@tonic-gate 656*7c478bd9Sstevel@tonic-gate (void) sm_strlcpy(user->mbdb_shell, vals[0], 657*7c478bd9Sstevel@tonic-gate sizeof(user->mbdb_shell)); 658*7c478bd9Sstevel@tonic-gate need &= ~NEED_SHELL; 659*7c478bd9Sstevel@tonic-gate } 660*7c478bd9Sstevel@tonic-gate else if (strcasecmp(attr, "uidNumber") == 0) 661*7c478bd9Sstevel@tonic-gate { 662*7c478bd9Sstevel@tonic-gate char *p; 663*7c478bd9Sstevel@tonic-gate 664*7c478bd9Sstevel@tonic-gate if (!bitset(NEED_UID, need)) 665*7c478bd9Sstevel@tonic-gate goto skip; 666*7c478bd9Sstevel@tonic-gate 667*7c478bd9Sstevel@tonic-gate for (p = vals[0]; *p != '\0'; p++) 668*7c478bd9Sstevel@tonic-gate { 669*7c478bd9Sstevel@tonic-gate /* allow negative numbers */ 670*7c478bd9Sstevel@tonic-gate if (p == vals[0] && *p == '-') 671*7c478bd9Sstevel@tonic-gate { 672*7c478bd9Sstevel@tonic-gate /* but not simply '-' */ 673*7c478bd9Sstevel@tonic-gate if (*(p + 1) == '\0') 674*7c478bd9Sstevel@tonic-gate goto skip; 675*7c478bd9Sstevel@tonic-gate } 676*7c478bd9Sstevel@tonic-gate else if (!isascii(*p) || !isdigit(*p)) 677*7c478bd9Sstevel@tonic-gate goto skip; 678*7c478bd9Sstevel@tonic-gate } 679*7c478bd9Sstevel@tonic-gate user->mbdb_uid = atoi(vals[0]); 680*7c478bd9Sstevel@tonic-gate need &= ~NEED_UID; 681*7c478bd9Sstevel@tonic-gate } 682*7c478bd9Sstevel@tonic-gate else if (strcasecmp(attr, "gidNumber") == 0) 683*7c478bd9Sstevel@tonic-gate { 684*7c478bd9Sstevel@tonic-gate char *p; 685*7c478bd9Sstevel@tonic-gate 686*7c478bd9Sstevel@tonic-gate if (!bitset(NEED_GID, need)) 687*7c478bd9Sstevel@tonic-gate goto skip; 688*7c478bd9Sstevel@tonic-gate 689*7c478bd9Sstevel@tonic-gate for (p = vals[0]; *p != '\0'; p++) 690*7c478bd9Sstevel@tonic-gate { 691*7c478bd9Sstevel@tonic-gate /* allow negative numbers */ 692*7c478bd9Sstevel@tonic-gate if (p == vals[0] && *p == '-') 693*7c478bd9Sstevel@tonic-gate { 694*7c478bd9Sstevel@tonic-gate /* but not simply '-' */ 695*7c478bd9Sstevel@tonic-gate if (*(p + 1) == '\0') 696*7c478bd9Sstevel@tonic-gate goto skip; 697*7c478bd9Sstevel@tonic-gate } 698*7c478bd9Sstevel@tonic-gate else if (!isascii(*p) || !isdigit(*p)) 699*7c478bd9Sstevel@tonic-gate goto skip; 700*7c478bd9Sstevel@tonic-gate } 701*7c478bd9Sstevel@tonic-gate user->mbdb_gid = atoi(vals[0]); 702*7c478bd9Sstevel@tonic-gate need &= ~NEED_GID; 703*7c478bd9Sstevel@tonic-gate } 704*7c478bd9Sstevel@tonic-gate 705*7c478bd9Sstevel@tonic-gate skip: 706*7c478bd9Sstevel@tonic-gate ldap_value_free(vals); 707*7c478bd9Sstevel@tonic-gate ldap_memfree(attr); 708*7c478bd9Sstevel@tonic-gate } 709*7c478bd9Sstevel@tonic-gate 710*7c478bd9Sstevel@tonic-gate errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld); 711*7c478bd9Sstevel@tonic-gate 712*7c478bd9Sstevel@tonic-gate /* 713*7c478bd9Sstevel@tonic-gate ** We check errno != LDAP_DECODING_ERROR since 714*7c478bd9Sstevel@tonic-gate ** OpenLDAP 1.X has a very ugly *undocumented* 715*7c478bd9Sstevel@tonic-gate ** hack of returning this error code from 716*7c478bd9Sstevel@tonic-gate ** ldap_next_attribute() if the library freed the 717*7c478bd9Sstevel@tonic-gate ** ber attribute. See: 718*7c478bd9Sstevel@tonic-gate ** http://www.openldap.org/lists/openldap-devel/9901/msg00064.html 719*7c478bd9Sstevel@tonic-gate */ 720*7c478bd9Sstevel@tonic-gate 721*7c478bd9Sstevel@tonic-gate if (errno != LDAP_SUCCESS && 722*7c478bd9Sstevel@tonic-gate errno != LDAP_DECODING_ERROR) 723*7c478bd9Sstevel@tonic-gate { 724*7c478bd9Sstevel@tonic-gate /* Must be an error */ 725*7c478bd9Sstevel@tonic-gate errno += E_LDAPBASE; 726*7c478bd9Sstevel@tonic-gate ret = EX_TEMPFAIL; 727*7c478bd9Sstevel@tonic-gate goto abort; 728*7c478bd9Sstevel@tonic-gate } 729*7c478bd9Sstevel@tonic-gate 730*7c478bd9Sstevel@tonic-gate abort: 731*7c478bd9Sstevel@tonic-gate save_errno = errno; 732*7c478bd9Sstevel@tonic-gate if (attr != NULL) 733*7c478bd9Sstevel@tonic-gate { 734*7c478bd9Sstevel@tonic-gate ldap_memfree(attr); 735*7c478bd9Sstevel@tonic-gate attr = NULL; 736*7c478bd9Sstevel@tonic-gate } 737*7c478bd9Sstevel@tonic-gate if (LDAPLMAP.ldap_res != NULL) 738*7c478bd9Sstevel@tonic-gate { 739*7c478bd9Sstevel@tonic-gate ldap_msgfree(LDAPLMAP.ldap_res); 740*7c478bd9Sstevel@tonic-gate LDAPLMAP.ldap_res = NULL; 741*7c478bd9Sstevel@tonic-gate } 742*7c478bd9Sstevel@tonic-gate if (ret == EX_OK) 743*7c478bd9Sstevel@tonic-gate { 744*7c478bd9Sstevel@tonic-gate if (need == 0) 745*7c478bd9Sstevel@tonic-gate { 746*7c478bd9Sstevel@tonic-gate (void) sm_strlcpy(user->mbdb_name, name, 747*7c478bd9Sstevel@tonic-gate sizeof(user->mbdb_name)); 748*7c478bd9Sstevel@tonic-gate save_errno = 0; 749*7c478bd9Sstevel@tonic-gate } 750*7c478bd9Sstevel@tonic-gate else 751*7c478bd9Sstevel@tonic-gate { 752*7c478bd9Sstevel@tonic-gate ret = EX_NOUSER; 753*7c478bd9Sstevel@tonic-gate save_errno = EINVAL; 754*7c478bd9Sstevel@tonic-gate } 755*7c478bd9Sstevel@tonic-gate } 756*7c478bd9Sstevel@tonic-gate errno = save_errno; 757*7c478bd9Sstevel@tonic-gate return ret; 758*7c478bd9Sstevel@tonic-gate } 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate /* 761*7c478bd9Sstevel@tonic-gate ** MBDB_LDAP_TERMINATE -- terminate connection to the mailbox database 762*7c478bd9Sstevel@tonic-gate ** 763*7c478bd9Sstevel@tonic-gate ** Parameters: 764*7c478bd9Sstevel@tonic-gate ** none. 765*7c478bd9Sstevel@tonic-gate ** 766*7c478bd9Sstevel@tonic-gate ** Results: 767*7c478bd9Sstevel@tonic-gate ** none. 768*7c478bd9Sstevel@tonic-gate */ 769*7c478bd9Sstevel@tonic-gate 770*7c478bd9Sstevel@tonic-gate static void 771*7c478bd9Sstevel@tonic-gate mbdb_ldap_terminate() 772*7c478bd9Sstevel@tonic-gate { 773*7c478bd9Sstevel@tonic-gate sm_ldap_close(&LDAPLMAP); 774*7c478bd9Sstevel@tonic-gate } 775*7c478bd9Sstevel@tonic-gate # endif /* _LDAP_EXAMPLE_ */ 776*7c478bd9Sstevel@tonic-gate #endif /* LDAPMAP */ 777