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 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * nis/getspent.c -- "nis" backend for nsswitch "shadow" database 27 */ 28 29 #pragma ident "%Z%%M% %I% %E% SMI" 30 31 #include <shadow.h> 32 #include <string.h> 33 #include "nis_common.h" 34 35 /* 36 * Most of the information in a struct spwd simply isn't available from the 37 * YP maps, we dummy out all the numeric fields and just get sp_namp and 38 * sp_pwdp (name and password) from the YP passwd map. Thus we don't 39 * use the str2ent() routine that's passed to us, but instead have our 40 * own dummy routine: 41 * 42 * Return values: 0 = success, 1 = parse error, 2 = erange ... 43 * The structure pointer passed in is a structure in the caller's space 44 * wherein the field pointers would be set to areas in the buffer if 45 * need be. instring and buffer should be separate areas. Let's not 46 * fight over crumbs. 47 */ 48 static int 49 nis_str2spent(instr, lenstr, ent, buffer, buflen) 50 const char *instr; 51 int lenstr; 52 void *ent; /* it is really (struct spwd *) */ 53 char *buffer; 54 int buflen; 55 { 56 struct spwd *spwd = (struct spwd *)ent; 57 char *p, *q, *r; 58 59 /* 60 * We know that instr != 0 because we're in 'nis', not 'files' 61 */ 62 if ((p = memchr(instr, ':', lenstr)) == 0) { 63 return (NSS_STR_PARSE_PARSE); 64 } 65 if ((q = memchr(p + 1, ':', lenstr - (p + 1 - instr))) == 0) { 66 return (NSS_STR_PARSE_PARSE); 67 } 68 /* Don't bother checking the rest of the YP passwd entry... */ 69 70 if (q + 1 - instr > buflen) { 71 return (NSS_STR_PARSE_ERANGE); 72 } 73 /* 74 * "name:password" is copied 75 */ 76 (void) memcpy(buffer, instr, q - instr); 77 if (spwd) { 78 buffer[p - instr] = '\0'; 79 buffer[q - instr] = '\0'; 80 81 spwd->sp_namp = buffer; 82 spwd->sp_pwdp = buffer + (p + 1 - instr); 83 spwd->sp_lstchg = -1; 84 spwd->sp_min = -1; 85 spwd->sp_max = -1; 86 spwd->sp_warn = -1; 87 spwd->sp_inact = -1; 88 spwd->sp_expire = -1; 89 spwd->sp_flag = 0; 90 } else { 91 /* 92 * NSS2: nscd is running. Return files format. 93 * 94 * name:password::::::: 95 */ 96 r = buffer + (q - instr); 97 *r = '\0'; 98 if (strlcat(buffer, ":::::::", buflen) >= buflen) 99 return (NSS_STR_PARSE_ERANGE); 100 } 101 return (NSS_STR_PARSE_SUCCESS); 102 } 103 104 typedef int (*cstr2ent_t)(const char *, int, void *, char *, int); 105 106 static nss_status_t 107 getbyname(be, a) 108 nis_backend_ptr_t be; 109 void *a; 110 { 111 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 112 cstr2ent_t save_c2e; 113 nss_status_t res; 114 struct spwd *spwd; 115 char *p; 116 117 save_c2e = argp->str2ent; 118 argp->str2ent = nis_str2spent; 119 res = _nss_nis_lookup(be, argp, 0, "passwd.byname", argp->key.name, 0); 120 spwd = (struct spwd *)argp->buf.result; 121 /* 122 * check for the C2 security flag "##" in the passwd field. 123 * If the first 2 chars in the passwd field is "##", get 124 * the user's passwd from passwd.adjunct.byname map. 125 * The lookup to this passwd.adjunct.byname map will only 126 * succeed if the caller's uid is 0 because only root user 127 * can use privilege port. 128 */ 129 if (res == NSS_SUCCESS) { 130 if (spwd) { 131 if ((spwd->sp_pwdp) && (*(spwd->sp_pwdp) == '#') && 132 (*(spwd->sp_pwdp + 1) == '#')) { 133 /* get password from passwd.adjunct.byname */ 134 res = _nss_nis_lookup_rsvdport(be, argp, 0, 135 "passwd.adjunct.byname", 136 argp->key.name, 0); 137 } 138 } else { 139 /* 140 * getent request from nscd 141 */ 142 if ((p = memchr(argp->buf.buffer, ':', 143 argp->buf.buflen)) == NULL) 144 return (NSS_STR_PARSE_PARSE); 145 if (strncmp(p + 1, "##", 2) == 0) 146 /* get password from passwd.adjunct.byname */ 147 res = _nss_nis_lookup_rsvdport(be, argp, 0, 148 "passwd.adjunct.byname", 149 argp->key.name, 0); 150 if (res == NSS_SUCCESS) { 151 argp->returnval = argp->buf.buffer; 152 argp->returnlen = strlen(argp->buf.buffer); 153 } 154 } 155 } 156 157 argp->str2ent = save_c2e; 158 return (res); 159 } 160 161 #define NIS_SP_GETENT 162 163 #ifdef NIS_SP_GETENT 164 165 static nss_status_t 166 getent(be, a) 167 nis_backend_ptr_t be; 168 void *a; 169 { 170 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 171 cstr2ent_t save_c2e; 172 nss_status_t res; 173 struct spwd *spwd; 174 char *p; 175 176 save_c2e = argp->str2ent; 177 argp->str2ent = nis_str2spent; 178 res = _nss_nis_getent_rigid(be, argp); 179 spwd = (struct spwd *)argp->buf.result; 180 /* 181 * check for the C2 security flag "##" in the passwd field. 182 * If the first 2 chars in the passwd field is "##", get 183 * the user's passwd from passwd.adjunct.byname map. 184 * The lookup to this passwd.adjunct.byname map will only 185 * succeed if the caller's uid is 0 because only root user 186 * can use privilege port. 187 */ 188 if (res == NSS_SUCCESS) { 189 if (spwd) { 190 if ((spwd->sp_pwdp) && (*(spwd->sp_pwdp) == '#') && 191 (*(spwd->sp_pwdp + 1) == '#')) { 192 /* get password from passwd.adjunct.byname */ 193 res = _nss_nis_lookup_rsvdport(be, argp, 0, 194 "passwd.adjunct.byname", 195 spwd->sp_namp, 0); 196 } 197 } else { 198 /* 199 * getent request from nscd 200 */ 201 if ((p = memchr(argp->buf.buffer, ':', 202 argp->buf.buflen)) == NULL) 203 return (NSS_STR_PARSE_PARSE); 204 if (strncmp(p + 1, "##", 2) == 0) { 205 /* need the name for the next search */ 206 *p = '\0'; 207 /* get password from passwd.adjunct.byname */ 208 res = _nss_nis_lookup_rsvdport(be, argp, 0, 209 "passwd.adjunct.byname", p, 0); 210 } 211 if (res == NSS_SUCCESS) { 212 argp->returnval = argp->buf.buffer; 213 argp->returnlen = strlen(argp->buf.buffer); 214 } 215 } 216 } 217 218 argp->str2ent = save_c2e; 219 return (res); 220 } 221 222 #endif /* NIS_SP_GETENT */ 223 224 static nis_backend_op_t shadow_ops[] = { 225 _nss_nis_destr, 226 _nss_nis_endent, 227 _nss_nis_setent, 228 #ifdef NIS_SP_GETENT 229 getent, 230 #else 231 0, 232 #endif /* NIS_SP_GETENT */ 233 getbyname 234 }; 235 236 /*ARGSUSED*/ 237 nss_backend_t * 238 _nss_nis_shadow_constr(dummy1, dummy2, dummy3) 239 const char *dummy1, *dummy2, *dummy3; 240 { 241 return (_nss_nis_constr(shadow_ops, 242 sizeof (shadow_ops) / sizeof (shadow_ops[0]), 243 "passwd.byname")); 244 } 245