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