Home | History | Annotate | Download | only in gen
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 #include "lint.h"
     30 #include <mtlib.h>
     31 #include <sys/types.h>
     32 #include <shadow.h>
     33 #include <stdlib.h>
     34 #include <string.h>
     35 #include <nss_dbdefs.h>
     36 #include <stdio.h>
     37 #include <synch.h>
     38 
     39 int str2spwd(const char *, int, void *,
     40 	char *, int);
     41 
     42 static DEFINE_NSS_DB_ROOT(db_root);
     43 static DEFINE_NSS_GETENT(context);
     44 
     45 void
     46 _nss_initf_shadow(nss_db_params_t *p)
     47 {
     48 	p->name	= NSS_DBNAM_SHADOW;
     49 	p->config_name    = NSS_DBNAM_PASSWD;	/* Use config for "passwd" */
     50 	p->default_config = NSS_DEFCONF_PASSWD;
     51 }
     52 
     53 struct spwd *
     54 getspnam_r(const char *name, struct spwd *result, char *buffer, int buflen)
     55 {
     56 	nss_XbyY_args_t arg;
     57 
     58 	NSS_XbyY_INIT(&arg, result, buffer, buflen, str2spwd);
     59 	arg.key.name = name;
     60 	(void) nss_search(&db_root, _nss_initf_shadow,
     61 	    NSS_DBOP_SHADOW_BYNAME, &arg);
     62 	return ((struct spwd *)NSS_XbyY_FINI(&arg));
     63 }
     64 
     65 void
     66 setspent(void)
     67 {
     68 	nss_setent(&db_root, _nss_initf_shadow, &context);
     69 }
     70 
     71 void
     72 endspent(void)
     73 {
     74 	nss_endent(&db_root, _nss_initf_shadow, &context);
     75 	nss_delete(&db_root);
     76 }
     77 
     78 struct spwd *
     79 getspent_r(struct spwd *result, char *buffer, int buflen)
     80 {
     81 	nss_XbyY_args_t arg;
     82 	char		*nam;
     83 
     84 	/* In getXXent_r(), protect the unsuspecting caller from +/- entries */
     85 
     86 	do {
     87 		NSS_XbyY_INIT(&arg, result, buffer, buflen, str2spwd);
     88 		/* No key to fill in */
     89 		(void) nss_getent(&db_root, _nss_initf_shadow, &context, &arg);
     90 	} while (arg.returnval != 0 &&
     91 	    (nam = ((struct spwd *)arg.returnval)->sp_namp) != 0 &&
     92 	    (*nam == '+' || *nam == '-'));
     93 
     94 	return (struct spwd *)NSS_XbyY_FINI(&arg);
     95 }
     96 
     97 struct spwd *
     98 fgetspent_r(FILE *f, struct spwd *result, char *buffer, int buflen)
     99 {
    100 	extern void	_nss_XbyY_fgets(FILE *, nss_XbyY_args_t *);
    101 	nss_XbyY_args_t	arg;
    102 
    103 	/* ... but in fgetXXent_r, the caller deserves any +/- entry he gets */
    104 
    105 	/* No key to fill in */
    106 	NSS_XbyY_INIT(&arg, result, buffer, buflen, str2spwd);
    107 	_nss_XbyY_fgets(f, &arg);
    108 	return (struct spwd *)NSS_XbyY_FINI(&arg);
    109 }
    110 
    111 typedef const char *constp;
    112 
    113 static int	/* 1 means success and more input, 0 means error or no more */
    114 getfield(constp *nextp, constp limit, int uns, void *valp)
    115 {
    116 	constp		p = *nextp;
    117 	char		*endfield;
    118 	char		numbuf[12];  /* Holds -2^31 and trailing ':' */
    119 	size_t		len;
    120 
    121 	if (p == 0 || p >= limit) {
    122 		return (0);
    123 	}
    124 	if (*p == ':') {
    125 		p++;
    126 		*nextp = p;
    127 		return (p < limit);
    128 	}
    129 	if ((len = limit - p) > sizeof (numbuf) - 1) {
    130 		len = sizeof (numbuf) - 1;
    131 	}
    132 	/*
    133 	 * We want to use strtol() and we have a readonly non-zero-terminated
    134 	 *   string, so first we copy and terminate the interesting bit.
    135 	 *   Ugh.  (It's convenient to terminate with a colon rather than \0).
    136 	 */
    137 	if ((endfield = memccpy(numbuf, p, ':', len)) == 0) {
    138 		if (len != limit - p) {
    139 			/* Error -- field is too big to be a legit number */
    140 			return (0);
    141 		}
    142 		numbuf[len] = ':';
    143 		p = limit;
    144 	} else {
    145 		p += (endfield - numbuf);
    146 	}
    147 	if (uns) {
    148 		unsigned long ux = strtoul(numbuf, &endfield, 10);
    149 		if (*endfield != ':') {
    150 			/* Error -- expected <integer><colon> */
    151 			return (0);
    152 		}
    153 		*((unsigned int *)valp) = (unsigned int)ux;
    154 	} else {
    155 		long x = strtol(numbuf, &endfield, 10);
    156 		if (*endfield != ':') {
    157 			/* Error -- expected <integer><colon> */
    158 			return (0);
    159 		}
    160 		*((int *)valp) = (int)x;
    161 	}
    162 	*nextp = p;
    163 	return (p < limit);
    164 }
    165 
    166 /*
    167  *  str2spwd() -- convert a string to a shadow passwd entry.  The parser is
    168  *	more liberal than the passwd or group parsers;  since it's legitimate
    169  *	for almost all the fields here to be blank, the parser lets one omit
    170  *	any number of blank fields at the end of the entry.  The acceptable
    171  *	forms for '+' and '-' entries are the same as those for normal entries.
    172  *  === Is this likely to do more harm than good?
    173  *
    174  * Return values: 0 = success, 1 = parse error, 2 = erange ...
    175  * The structure pointer passed in is a structure in the caller's space
    176  * wherein the field pointers would be set to areas in the buffer if
    177  * need be. instring and buffer should be separate areas.
    178  */
    179 int
    180 str2spwd(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
    181 {
    182 	struct spwd	*shadow	= (struct spwd *)ent;
    183 	const char	*p = instr, *limit;
    184 	char	*bufp;
    185 	int	black_magic;
    186 	size_t	lencopy;
    187 
    188 	limit = p + lenstr;
    189 	if ((p = memchr(instr, ':', lenstr)) == 0 ||
    190 	    ++p >= limit ||
    191 	    (p = memchr(p, ':', limit - p)) == 0) {
    192 		lencopy = (size_t)lenstr;
    193 		p = 0;
    194 	} else {
    195 		lencopy = p - instr;
    196 		p++;
    197 	}
    198 	if (lencopy + 1 > buflen) {
    199 		return (NSS_STR_PARSE_ERANGE);
    200 	}
    201 
    202 	if (instr != buffer) {
    203 		/* Overlapping buffer copies are OK */
    204 		(void) memmove(buffer, instr, lencopy);
    205 		buffer[lencopy] = 0;
    206 	}
    207 
    208 	/* quick exit do not entry fill if not needed */
    209 	if (ent == (void *)NULL)
    210 		return (NSS_STR_PARSE_SUCCESS);
    211 
    212 	black_magic = (*instr == '+' || *instr == '-');
    213 	shadow->sp_namp = bufp = buffer;
    214 	shadow->sp_pwdp	= 0;
    215 	shadow->sp_lstchg = -1;
    216 	shadow->sp_min	= -1;
    217 	shadow->sp_max	= -1;
    218 	shadow->sp_warn	= -1;
    219 	shadow->sp_inact = -1;
    220 	shadow->sp_expire = -1;
    221 	shadow->sp_flag	= 0;
    222 
    223 	if ((bufp = strchr(bufp, ':')) == 0) {
    224 		if (black_magic)
    225 			return (NSS_STR_PARSE_SUCCESS);
    226 		else
    227 			return (NSS_STR_PARSE_PARSE);
    228 	}
    229 	*bufp++ = '\0';
    230 
    231 	shadow->sp_pwdp = bufp;
    232 	if (instr == 0) {
    233 		if ((bufp = strchr(bufp, ':')) == 0) {
    234 			if (black_magic)
    235 				return (NSS_STR_PARSE_SUCCESS);
    236 			else
    237 				return (NSS_STR_PARSE_PARSE);
    238 		}
    239 		*bufp++ = '\0';
    240 		p = bufp;
    241 	} /* else p was set when we copied name and passwd into the buffer */
    242 
    243 	if (!getfield(&p, limit, 0, &shadow->sp_lstchg))
    244 			return (NSS_STR_PARSE_SUCCESS);
    245 	if (!getfield(&p, limit, 0, &shadow->sp_min))
    246 			return (NSS_STR_PARSE_SUCCESS);
    247 	if (!getfield(&p, limit, 0, &shadow->sp_max))
    248 			return (NSS_STR_PARSE_SUCCESS);
    249 	if (!getfield(&p, limit, 0, &shadow->sp_warn))
    250 			return (NSS_STR_PARSE_SUCCESS);
    251 	if (!getfield(&p, limit, 0, &shadow->sp_inact))
    252 			return (NSS_STR_PARSE_SUCCESS);
    253 	if (!getfield(&p, limit, 0, &shadow->sp_expire))
    254 			return (NSS_STR_PARSE_SUCCESS);
    255 	if (!getfield(&p, limit, 1, &shadow->sp_flag))
    256 			return (NSS_STR_PARSE_SUCCESS);
    257 	if (p != limit) {
    258 		/* Syntax error -- garbage at end of line */
    259 		return (NSS_STR_PARSE_PARSE);
    260 	}
    261 	return (NSS_STR_PARSE_SUCCESS);
    262 }
    263