xref: /onnv-gate/usr/src/lib/nsswitch/compat/common/getspent.c (revision 11262:b7ebfbf2359e)
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*11262SRajagopal.Andra@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
232830Sdjl  * Use is subject to license terms.
242830Sdjl  */
252830Sdjl /*
260Sstevel@tonic-gate  *	getspent.c
270Sstevel@tonic-gate  *
280Sstevel@tonic-gate  * lib/nsswitch/compat/getspent.c -- name-service-switch backend for getspnam()
290Sstevel@tonic-gate  *   It looks in /etc/shadow; if it finds shadow entries there that begin
300Sstevel@tonic-gate  *   with "+" or "-", it consults other services.  By default it uses NIS (YP),
310Sstevel@tonic-gate  *   but the user can override this with a "passwd_compat" entry in
320Sstevel@tonic-gate  *   /etc/nsswitch.conf, e.g.
33*11262SRajagopal.Andra@Sun.COM  *			passwd_compat: ldap
340Sstevel@tonic-gate  * The main criterion for this code is that it behave in the same way as
350Sstevel@tonic-gate  * the code for getpwnam() and friends (in getpwent.c).  Note that it uses
360Sstevel@tonic-gate  * the same nsswitch.conf entry, not a separate entry for "shadow_compat".
370Sstevel@tonic-gate  *
380Sstevel@tonic-gate  * Caveats:
390Sstevel@tonic-gate  *    -	More than one source may be specified, with the usual switch semantics,
400Sstevel@tonic-gate  *	but having multiple sources here is definitely odd.
410Sstevel@tonic-gate  *    -	People who recursively specify "compat" deserve what they get.
420Sstevel@tonic-gate  *    -	Entries that begin with "+@" or "-@" are interpreted using
430Sstevel@tonic-gate  *	getnetgrent() and innetgr(), which use the "netgroup" entry in
440Sstevel@tonic-gate  *	/etc/nsswitch.conf.  If the sources for "passwd_compat" and "netgroup"
450Sstevel@tonic-gate  *	differ, everything should work fine, but the semantics will be pretty
460Sstevel@tonic-gate  *	confusing.
470Sstevel@tonic-gate  */
480Sstevel@tonic-gate 
490Sstevel@tonic-gate #include <shadow.h>
500Sstevel@tonic-gate #include <string.h>
510Sstevel@tonic-gate #include <stdlib.h>
520Sstevel@tonic-gate #include "compat_common.h"
530Sstevel@tonic-gate 
540Sstevel@tonic-gate static DEFINE_NSS_DB_ROOT(db_root);
550Sstevel@tonic-gate 
562830Sdjl static void
_nss_initf_shadow_compat(p)570Sstevel@tonic-gate _nss_initf_shadow_compat(p)
580Sstevel@tonic-gate 	nss_db_params_t	*p;
590Sstevel@tonic-gate {
600Sstevel@tonic-gate 	p->name		  = NSS_DBNAM_SHADOW;
610Sstevel@tonic-gate 	p->config_name	  = NSS_DBNAM_PASSWD_COMPAT;
620Sstevel@tonic-gate 	p->default_config = NSS_DEFCONF_PASSWD_COMPAT;
630Sstevel@tonic-gate }
640Sstevel@tonic-gate 
650Sstevel@tonic-gate static const char *
get_spnamp(argp)660Sstevel@tonic-gate get_spnamp(argp)
670Sstevel@tonic-gate 	nss_XbyY_args_t		*argp;
680Sstevel@tonic-gate {
690Sstevel@tonic-gate 	struct spwd		*s = (struct spwd *)argp->returnval;
700Sstevel@tonic-gate 
710Sstevel@tonic-gate 	return (s->sp_namp);
720Sstevel@tonic-gate }
730Sstevel@tonic-gate 
740Sstevel@tonic-gate static int
check_spnamp(argp)750Sstevel@tonic-gate check_spnamp(argp)
760Sstevel@tonic-gate 	nss_XbyY_args_t		*argp;
770Sstevel@tonic-gate {
780Sstevel@tonic-gate 	struct spwd		*s = (struct spwd *)argp->returnval;
790Sstevel@tonic-gate 
800Sstevel@tonic-gate 	return (strcmp(s->sp_namp, argp->key.name) == 0);
810Sstevel@tonic-gate }
820Sstevel@tonic-gate 
830Sstevel@tonic-gate static nss_status_t
getbyname(be,a)840Sstevel@tonic-gate getbyname(be, a)
850Sstevel@tonic-gate 	compat_backend_ptr_t	be;
860Sstevel@tonic-gate 	void			*a;
870Sstevel@tonic-gate {
882830Sdjl 	nss_XbyY_args_t		*argp = (nss_XbyY_args_t *)a;
890Sstevel@tonic-gate 
900Sstevel@tonic-gate 	return (_nss_compat_XY_all(be, argp, check_spnamp,
910Sstevel@tonic-gate 				NSS_DBOP_SHADOW_BYNAME));
920Sstevel@tonic-gate }
930Sstevel@tonic-gate 
940Sstevel@tonic-gate /*ARGSUSED*/
950Sstevel@tonic-gate static int
merge_spents(be,argp,fields)960Sstevel@tonic-gate merge_spents(be, argp, fields)
970Sstevel@tonic-gate 	compat_backend_ptr_t	be;
980Sstevel@tonic-gate 	nss_XbyY_args_t		*argp;
990Sstevel@tonic-gate 	const char		**fields;
1000Sstevel@tonic-gate {
1010Sstevel@tonic-gate 	struct spwd		*sp	= (struct spwd *)argp->buf.result;
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate 	/*
1040Sstevel@tonic-gate 	 * Don't allow overriding of the username;  apart from that,
1050Sstevel@tonic-gate 	 *   anything is fair game.
1060Sstevel@tonic-gate 	 */
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate 	if (fields[1] != 0) {
1090Sstevel@tonic-gate 		size_t	namelen = strlen(sp->sp_namp) + 1;
1100Sstevel@tonic-gate 		size_t	passlen = strlen(fields[1])   + 1;
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 		/* ===> Probably merits an explanation... */
1130Sstevel@tonic-gate 		if (namelen + passlen > argp->buf.buflen) {
1140Sstevel@tonic-gate 			return (NSS_STR_PARSE_ERANGE);
1150Sstevel@tonic-gate 		}
1160Sstevel@tonic-gate 		if (sp->sp_namp != argp->buf.buffer) {
1172830Sdjl 			(void) memmove(argp->buf.buffer,
1182830Sdjl 				sp->sp_namp, namelen);
1190Sstevel@tonic-gate 			sp->sp_namp = argp->buf.buffer;
1200Sstevel@tonic-gate 		}
1212830Sdjl 		(void) memcpy(argp->buf.buffer + namelen,
1222830Sdjl 			fields[1], passlen);
1230Sstevel@tonic-gate 	}
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate #define	override(field, longp)				\
1260Sstevel@tonic-gate 	if ((field) != 0) {				\
1270Sstevel@tonic-gate 		char	*end;				\
1280Sstevel@tonic-gate 		long	val = strtol(field, &end, 10);	\
1290Sstevel@tonic-gate 							\
1300Sstevel@tonic-gate 		if (*end == '\0') {			\
1310Sstevel@tonic-gate 			*(longp) = val;			\
1320Sstevel@tonic-gate 		} else {				\
1330Sstevel@tonic-gate 			return (NSS_STR_PARSE_PARSE);	\
1340Sstevel@tonic-gate 		}					\
1350Sstevel@tonic-gate 	}
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate 	/* do not override last changed date, it never gets reset. */
1380Sstevel@tonic-gate 	/* override(fields[2], &sp->sp_lstchg); */
1390Sstevel@tonic-gate 	override(fields[3], &sp->sp_min);
1400Sstevel@tonic-gate 	override(fields[4], &sp->sp_max);
1410Sstevel@tonic-gate 	override(fields[5], &sp->sp_warn);
1420Sstevel@tonic-gate 	override(fields[6], &sp->sp_inact);
1430Sstevel@tonic-gate 	override(fields[7], &sp->sp_expire);
1440Sstevel@tonic-gate 	override(fields[8], &sp->sp_flag);
1452830Sdjl 
1462830Sdjl 	/*
1472830Sdjl 	 * if asked, return the data in /etc file format
1482830Sdjl 	 */
1492830Sdjl 	if (be->return_string_data == 1) {
1502830Sdjl 		int	n;
1515920Ssdussud 		char	b[16 * 7];
1522830Sdjl 
1532830Sdjl 		/* reset the result ptr to the original value */
1542830Sdjl 		argp->buf.result = NULL;
1552830Sdjl 
1565920Ssdussud #define	printnum(i, num)	\
1575920Ssdussud     sprintf(b + (i * 16), "%d", num)) ? b + (i * 16) : ""
1582830Sdjl 
1592830Sdjl 		n = snprintf(argp->buf.buffer, argp->buf.buflen,
1602830Sdjl 			"%s:%s:%s:%s:%s:%s:%s:%s:%s", sp->sp_namp,
1612830Sdjl 			(sp->sp_pwdp ? sp->sp_pwdp : ""),
1625920Ssdussud 			(sp->sp_lstchg >= 0 && printnum(0, sp->sp_lstchg),
1635920Ssdussud 			(sp->sp_min >= 0 && printnum(1, sp->sp_min),
1645920Ssdussud 			(sp->sp_max >= 0 && printnum(2, sp->sp_max),
1655920Ssdussud 			(sp->sp_warn > 0 && printnum(3, sp->sp_warn),
1665920Ssdussud 			(sp->sp_inact > 0 && printnum(4, sp->sp_inact),
1675920Ssdussud 			(sp->sp_expire > 0 && printnum(5, sp->sp_expire),
1685920Ssdussud 			(sp->sp_flag != 0 && printnum(6, sp->sp_flag));
1692830Sdjl 
1702830Sdjl 		if (n > argp->buf.buflen)
1712830Sdjl 			return (NSS_STR_PARSE_ERANGE);
1722830Sdjl 		else {
1732830Sdjl 			argp->returnlen = n - 1;
1742830Sdjl 			return (NSS_SUCCESS);
1752830Sdjl 		}
1762830Sdjl 
1772830Sdjl 	} else
1782830Sdjl 		return (NSS_STR_PARSE_SUCCESS);
1790Sstevel@tonic-gate }
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate static compat_backend_op_t shadow_ops[] = {
1820Sstevel@tonic-gate 	_nss_compat_destr,
1830Sstevel@tonic-gate 	_nss_compat_endent,
1840Sstevel@tonic-gate 	_nss_compat_setent,
1850Sstevel@tonic-gate 	_nss_compat_getent,
1860Sstevel@tonic-gate 	getbyname
1870Sstevel@tonic-gate };
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate /*ARGSUSED*/
1900Sstevel@tonic-gate nss_backend_t *
1910Sstevel@tonic-gate _nss_compat_shadow_constr(dummy1, dummy2, dummy3)
1920Sstevel@tonic-gate 	const char	*dummy1, *dummy2, *dummy3;
1930Sstevel@tonic-gate {
1940Sstevel@tonic-gate 	return (_nss_compat_constr(shadow_ops,
1950Sstevel@tonic-gate 				sizeof (shadow_ops) / sizeof (shadow_ops[0]),
1960Sstevel@tonic-gate 				SHADOW,
1970Sstevel@tonic-gate 				NSS_LINELEN_SHADOW,
1980Sstevel@tonic-gate 				&db_root,
1990Sstevel@tonic-gate 				_nss_initf_shadow_compat,
2000Sstevel@tonic-gate 				1,
2010Sstevel@tonic-gate 				get_spnamp,
2020Sstevel@tonic-gate 				merge_spents));
2030Sstevel@tonic-gate }
204