10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 52830Sdjl * Common Development and Distribution License (the "License"). 62830Sdjl * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*8040SBaban.Kenkre@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 232830Sdjl * Use is subject to license terms. 240Sstevel@tonic-gate * 252830Sdjl * files/getpwnam.c -- "files" backend for nsswitch "passwd" database 260Sstevel@tonic-gate */ 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <pwd.h> 290Sstevel@tonic-gate #include <shadow.h> 300Sstevel@tonic-gate #include <unistd.h> /* for PF_PATH */ 310Sstevel@tonic-gate #include "files_common.h" 320Sstevel@tonic-gate #include <strings.h> 332830Sdjl #include <stdlib.h> 340Sstevel@tonic-gate 352830Sdjl static uint_t 362830Sdjl hash_pwname(nss_XbyY_args_t *argp, int keyhash, const char *line, 372830Sdjl int linelen) 380Sstevel@tonic-gate { 392830Sdjl const char *name; 402830Sdjl int namelen, i; 412830Sdjl uint_t hash = 0; 420Sstevel@tonic-gate 432830Sdjl if (keyhash) { 442830Sdjl name = argp->key.name; 452830Sdjl namelen = strlen(name); 462830Sdjl } else { 472830Sdjl name = line; 482830Sdjl namelen = 0; 492830Sdjl while (linelen-- && *line++ != ':') 502830Sdjl namelen++; 512830Sdjl } 520Sstevel@tonic-gate 532830Sdjl for (i = 0; i < namelen; i++) 542830Sdjl hash = hash * 15 + name[i]; 550Sstevel@tonic-gate return (hash); 560Sstevel@tonic-gate } 570Sstevel@tonic-gate 582830Sdjl static uint_t 592830Sdjl hash_pwuid(nss_XbyY_args_t *argp, int keyhash, const char *line, 602830Sdjl int linelen) 610Sstevel@tonic-gate { 622830Sdjl uint_t id; 632830Sdjl const char *linep, *limit, *end; 642830Sdjl 652830Sdjl linep = line; 662830Sdjl limit = line + linelen; 672830Sdjl 682830Sdjl if (keyhash) 692830Sdjl return ((uint_t)argp->key.uid); 702830Sdjl 71*8040SBaban.Kenkre@Sun.COM while (linep < limit && *linep++ != ':') /* skip username */ 72*8040SBaban.Kenkre@Sun.COM continue; 73*8040SBaban.Kenkre@Sun.COM while (linep < limit && *linep++ != ':') /* skip password */ 74*8040SBaban.Kenkre@Sun.COM continue; 752830Sdjl if (linep == limit) 762830Sdjl return (UID_NOBODY); 772830Sdjl 782830Sdjl /* uid */ 792830Sdjl end = linep; 80*8040SBaban.Kenkre@Sun.COM id = (uint_t)strtoul(linep, (char **)&end, 10); 812830Sdjl 822830Sdjl /* empty uid */ 832830Sdjl if (linep == end) 842830Sdjl return (UID_NOBODY); 852830Sdjl 862830Sdjl return (id); 870Sstevel@tonic-gate } 880Sstevel@tonic-gate 890Sstevel@tonic-gate static files_hash_func hash_pw[2] = { hash_pwname, hash_pwuid }; 900Sstevel@tonic-gate 910Sstevel@tonic-gate static files_hash_t hashinfo = { 920Sstevel@tonic-gate DEFAULTMUTEX, 930Sstevel@tonic-gate sizeof (struct passwd), 940Sstevel@tonic-gate NSS_BUFLEN_PASSWD, 950Sstevel@tonic-gate 2, 960Sstevel@tonic-gate hash_pw 970Sstevel@tonic-gate }; 980Sstevel@tonic-gate 990Sstevel@tonic-gate static int 1002830Sdjl check_pwname(nss_XbyY_args_t *argp, const char *line, int linelen) 1010Sstevel@tonic-gate { 1022830Sdjl const char *linep, *limit; 1032830Sdjl const char *keyp = argp->key.name; 1042830Sdjl 1052830Sdjl linep = line; 1062830Sdjl limit = line + linelen; 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate /* +/- entries valid for compat source only */ 1092830Sdjl if (linelen == 0 || *line == '+' || *line == '-') 1100Sstevel@tonic-gate return (0); 1112830Sdjl while (*keyp && linep < limit && *keyp == *linep) { 1122830Sdjl keyp++; 1132830Sdjl linep++; 1142830Sdjl } 1152830Sdjl return (linep < limit && *keyp == '\0' && *linep == ':'); 1160Sstevel@tonic-gate } 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate static nss_status_t 1190Sstevel@tonic-gate getbyname(be, a) 1200Sstevel@tonic-gate files_backend_ptr_t be; 1210Sstevel@tonic-gate void *a; 1220Sstevel@tonic-gate { 1230Sstevel@tonic-gate return (_nss_files_XY_hash(be, a, 0, &hashinfo, 0, check_pwname)); 1240Sstevel@tonic-gate } 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate static int 1272830Sdjl check_pwuid(nss_XbyY_args_t *argp, const char *line, int linelen) 1280Sstevel@tonic-gate { 1292830Sdjl const char *linep, *limit, *end; 130*8040SBaban.Kenkre@Sun.COM ulong_t pw_uid; 1312830Sdjl 1322830Sdjl linep = line; 1332830Sdjl limit = line + linelen; 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate /* +/- entries valid for compat source only */ 1362830Sdjl if (linelen == 0 || *line == '+' || *line == '-') 1372830Sdjl return (0); 1382830Sdjl 139*8040SBaban.Kenkre@Sun.COM while (linep < limit && *linep++ != ':') /* skip username */ 140*8040SBaban.Kenkre@Sun.COM continue; 141*8040SBaban.Kenkre@Sun.COM while (linep < limit && *linep++ != ':') /* skip password */ 142*8040SBaban.Kenkre@Sun.COM continue; 1432830Sdjl if (linep == limit) 1440Sstevel@tonic-gate return (0); 1452830Sdjl 1462830Sdjl /* uid */ 1472830Sdjl end = linep; 148*8040SBaban.Kenkre@Sun.COM pw_uid = strtoul(linep, (char **)&end, 10); 1492830Sdjl 150*8040SBaban.Kenkre@Sun.COM /* check if the uid is empty or overflows */ 151*8040SBaban.Kenkre@Sun.COM if (linep == end || pw_uid > UINT32_MAX) 1522830Sdjl return (0); 1532830Sdjl 154*8040SBaban.Kenkre@Sun.COM return ((uid_t)pw_uid == argp->key.uid); 1550Sstevel@tonic-gate } 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate static nss_status_t 1580Sstevel@tonic-gate getbyuid(be, a) 1590Sstevel@tonic-gate files_backend_ptr_t be; 1600Sstevel@tonic-gate void *a; 1610Sstevel@tonic-gate { 162*8040SBaban.Kenkre@Sun.COM nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 163*8040SBaban.Kenkre@Sun.COM 164*8040SBaban.Kenkre@Sun.COM if (argp->key.uid > MAXUID) 165*8040SBaban.Kenkre@Sun.COM return (NSS_NOTFOUND); 166*8040SBaban.Kenkre@Sun.COM return (_nss_files_XY_hash(be, argp, 0, &hashinfo, 1, check_pwuid)); 167*8040SBaban.Kenkre@Sun.COM } 168*8040SBaban.Kenkre@Sun.COM 169*8040SBaban.Kenkre@Sun.COM /* 170*8040SBaban.Kenkre@Sun.COM * Validates passwd entry replacing uid/gid > MAXUID by ID_NOBODY. 171*8040SBaban.Kenkre@Sun.COM */ 172*8040SBaban.Kenkre@Sun.COM int 173*8040SBaban.Kenkre@Sun.COM validate_passwd_ids(char *line, int *linelenp, int buflen, int extra_chars) 174*8040SBaban.Kenkre@Sun.COM { 175*8040SBaban.Kenkre@Sun.COM char *linep, *limit, *uidp, *gidp; 176*8040SBaban.Kenkre@Sun.COM uid_t uid; 177*8040SBaban.Kenkre@Sun.COM gid_t gid; 178*8040SBaban.Kenkre@Sun.COM ulong_t uidl, gidl; 179*8040SBaban.Kenkre@Sun.COM int olduidlen, oldgidlen, idlen; 180*8040SBaban.Kenkre@Sun.COM int linelen = *linelenp, newlinelen; 181*8040SBaban.Kenkre@Sun.COM 182*8040SBaban.Kenkre@Sun.COM /* 183*8040SBaban.Kenkre@Sun.COM * +name entries in passwd(4) do not override uid and gid 184*8040SBaban.Kenkre@Sun.COM * values. Therefore no need to validate the ids in these 185*8040SBaban.Kenkre@Sun.COM * entries. 186*8040SBaban.Kenkre@Sun.COM */ 187*8040SBaban.Kenkre@Sun.COM if (linelen == 0 || *line == '+' || *line == '-') 188*8040SBaban.Kenkre@Sun.COM return (NSS_STR_PARSE_SUCCESS); 189*8040SBaban.Kenkre@Sun.COM 190*8040SBaban.Kenkre@Sun.COM linep = line; 191*8040SBaban.Kenkre@Sun.COM limit = line + linelen; 192*8040SBaban.Kenkre@Sun.COM 193*8040SBaban.Kenkre@Sun.COM while (linep < limit && *linep++ != ':') /* skip username */ 194*8040SBaban.Kenkre@Sun.COM continue; 195*8040SBaban.Kenkre@Sun.COM while (linep < limit && *linep++ != ':') /* skip password */ 196*8040SBaban.Kenkre@Sun.COM continue; 197*8040SBaban.Kenkre@Sun.COM if (linep == limit) 198*8040SBaban.Kenkre@Sun.COM return (NSS_STR_PARSE_PARSE); 199*8040SBaban.Kenkre@Sun.COM 200*8040SBaban.Kenkre@Sun.COM uidp = linep; 201*8040SBaban.Kenkre@Sun.COM uidl = strtoul(uidp, (char **)&linep, 10); /* grab uid */ 202*8040SBaban.Kenkre@Sun.COM olduidlen = linep - uidp; 203*8040SBaban.Kenkre@Sun.COM if (++linep >= limit || olduidlen == 0) 204*8040SBaban.Kenkre@Sun.COM return (NSS_STR_PARSE_PARSE); 205*8040SBaban.Kenkre@Sun.COM 206*8040SBaban.Kenkre@Sun.COM gidp = linep; 207*8040SBaban.Kenkre@Sun.COM gidl = strtoul(gidp, (char **)&linep, 10); /* grab gid */ 208*8040SBaban.Kenkre@Sun.COM oldgidlen = linep - gidp; 209*8040SBaban.Kenkre@Sun.COM if (linep >= limit || oldgidlen == 0) 210*8040SBaban.Kenkre@Sun.COM return (NSS_STR_PARSE_PARSE); 211*8040SBaban.Kenkre@Sun.COM 212*8040SBaban.Kenkre@Sun.COM if (uidl <= MAXUID && gidl <= MAXUID) 213*8040SBaban.Kenkre@Sun.COM return (NSS_STR_PARSE_SUCCESS); 214*8040SBaban.Kenkre@Sun.COM uid = (uidl > MAXUID) ? UID_NOBODY : (uid_t)uidl; 215*8040SBaban.Kenkre@Sun.COM gid = (gidl > MAXUID) ? GID_NOBODY : (gid_t)gidl; 216*8040SBaban.Kenkre@Sun.COM 217*8040SBaban.Kenkre@Sun.COM /* Check if we have enough space in the buffer */ 218*8040SBaban.Kenkre@Sun.COM idlen = snprintf(NULL, 0, "%u:%u", uid, gid); 219*8040SBaban.Kenkre@Sun.COM newlinelen = linelen + idlen - olduidlen - oldgidlen - 1; 220*8040SBaban.Kenkre@Sun.COM if (newlinelen + extra_chars > buflen) 221*8040SBaban.Kenkre@Sun.COM return (NSS_STR_PARSE_ERANGE); 222*8040SBaban.Kenkre@Sun.COM 223*8040SBaban.Kenkre@Sun.COM /* Replace ephemeral ids by ID_NOBODY */ 224*8040SBaban.Kenkre@Sun.COM (void) bcopy(linep, uidp + idlen, limit - linep + extra_chars); 225*8040SBaban.Kenkre@Sun.COM (void) snprintf(uidp, idlen + 1, "%u:%u", uid, gid); 226*8040SBaban.Kenkre@Sun.COM *(uidp + idlen) = ':'; /* restore : that was overwritten by snprintf */ 227*8040SBaban.Kenkre@Sun.COM *linelenp = newlinelen; 228*8040SBaban.Kenkre@Sun.COM return (NSS_STR_PARSE_SUCCESS); 2290Sstevel@tonic-gate } 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate static files_backend_op_t passwd_ops[] = { 2320Sstevel@tonic-gate _nss_files_destr, 2330Sstevel@tonic-gate _nss_files_endent, 2340Sstevel@tonic-gate _nss_files_setent, 2350Sstevel@tonic-gate _nss_files_getent_rigid, 2360Sstevel@tonic-gate getbyname, 2370Sstevel@tonic-gate getbyuid 2380Sstevel@tonic-gate }; 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate /*ARGSUSED*/ 2410Sstevel@tonic-gate nss_backend_t * 2420Sstevel@tonic-gate _nss_files_passwd_constr(dummy1, dummy2, dummy3) 2430Sstevel@tonic-gate const char *dummy1, *dummy2, *dummy3; 2440Sstevel@tonic-gate { 2450Sstevel@tonic-gate return (_nss_files_constr(passwd_ops, 2460Sstevel@tonic-gate sizeof (passwd_ops) / sizeof (passwd_ops[0]), 2470Sstevel@tonic-gate PF_PATH, 2480Sstevel@tonic-gate NSS_LINELEN_PASSWD, 2490Sstevel@tonic-gate &hashinfo)); 2500Sstevel@tonic-gate } 251