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