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
hash_pwname(nss_XbyY_args_t * argp,int keyhash,const char * line,int linelen)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
hash_pwuid(nss_XbyY_args_t * argp,int keyhash,const char * line,int linelen)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
check_pwname(nss_XbyY_args_t * argp,const char * line,int linelen)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
getbyname(be,a)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
check_pwuid(nss_XbyY_args_t * argp,const char * line,int linelen)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
getbyuid(be,a)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
validate_passwd_ids(char * line,int * linelenp,int buflen,int extra_chars)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 *
_nss_files_passwd_constr(dummy1,dummy2,dummy3)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