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