compat_common.c revision 2
2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 1992, 2012, Oracle and/or its affiliates. All rights reserved. 2N/A * Common code and structures used by name-service-switch "compat" backends. 2N/A * Most of the code in the "compat" backend is a perverted form of code from 2N/A * the "files" backend; this file is no exception. 2N/A * This should be in a header. 2N/A * str2auuser_s is very simple version of the str2auuser() that can be found in 2N/A * libc. They only copy the user name into the au_user_str_t structure 2N/A * (so check on user name can be performed). 2N/A * Routines to manage list of "-" users for get{pw, sp, gr}ent(). Current 2N/A * implementation is completely moronic; we use a linked list. But then 2N/A * that's what it's always done in 4.x... 2N/A * === Should get smart and malloc the string and pointer as one 2N/A * object rather than two. 2N/A * Lookup and enumeration routines for +@group and -@group. 2N/A * is really healthy. The set/get/end routines below duplicate code 2N/A * from that file, but keep the state information per-backend-instance 2N/A * instead of just per-process. 2N/A * resource-management quotas right, but this will have to do. 2N/A * ===> Need comment to explain that this first "if" is optimizing 2N/A * for the same-netgroup-as-last-time case 2N/A#
define MAXFIELDS 9 /* Sufficient for passwd (7), shadow (9), group (4) */ 2N/A * Potential optimization: only perform the field-splitting nonsense 2N/A * once per input line (at present, "+" and "+@netgroup" entries 2N/A * will cause us to do this multiple times in getent() requests). 2N/A const char *r = (q == 0) ?
end : q;
2N/A /* Skip the colon at (*q) */ 2N/A * return result here if /etc file format is requested 2N/A /* No real overrides, return (*args) intact */ 2N/A * The zero'th field is always nonempty (+/-...), but at least 2N/A * one other field was also nonempty, i.e. wants to override 2N/A/* ===> Very likely the wrong thing to do... */ 2N/A /* Backend isn't initialized properly? */ 2N/A /* ===> ??? nss_endent(be->db_rootp, be->db_initf, &be->db_context); */ 2N/A /* ===> ?? netgroup stuff? */ 2N/A * Question: from the point of view of resource-freeing vs. time to 2N/A * start up again, how much should we do in endent() and how much 2N/A * in the destructor? 2N/A /* linelen >= 1 (since fgets didn't return 0) */ 2N/A * ===> The code below that calls read_line() doesn't 2N/A * play by the rules; it assumes in places that 2N/A * the line is null-terminated. For now we'll 2N/A /* Line is last line in file, and has no newline */ 2N/A /* Line too long for buffer; toss it and loop for next line */ 2N/A /* ===== should syslog() in cases where previous code did */ 2N/A * assume a NULL buf.result pointer is an indication 2N/A * that the lookup result should be returned in /etc 2N/A * file format (if called from _nss_compat_getent(), 2N/A * be->return_string_data and argp->buf.result 2N/A * would be set already if argp->buf.result is NULL) 2N/A * the code executed later needs the result struct 2N/A * use an alternate str2ent function if necessary 2N/A * Optimization: if the entry doesn't contain the 2N/A * filter string then it can't be the entry we want, 2N/A * so don't bother looking more closely at it. 2N/A *
last-- =
'\0';
/* Nuke '\n' or #comment */ 2N/A * Skip leading whitespace. Normally there isn't 2N/A * any, so it's not worth calling strspn(). 2N/A * Found something non-blank on the line. Skip back 2N/A * over any trailing whitespace; since we know 2N/A * there's non-whitespace earlier in the line, 2N/A * checking for termination is easy. 2N/A /* copy string data to result buffer */ 2N/A * stayopen is set to 0 by default in order to close the opened 2N/A * file. Some applications may break if it is set to 1. 2N/A * tell the nss_search() and nss_getent() below 2N/A * if the result should be returned in the /etc 2N/A * The data is already marshalled into 2N/A * struct passwd or group. 2N/A * The data needs to be returned in string format therefore 2N/A * validate the return string. 2N/A * assume a NULL buf.result pointer is an indication 2N/A * that the lookup result should be returned in /etc 2N/A * the code executed later needs the result struct 2N/A /* Simple, wholesome, God-fearing entry */ 2N/A * copy string data to 2N/A/* ===> Check the Dani logic here... */ 2N/A /* should we just skip this one long line ? */ 2N/A }
/* else if (parsestat == NSS_STR_PARSE_PARSE) */ 2N/A/* ==> ?? */ continue;
2N/A * Process "+", "+name", "+@netgroup", "-name" or "-@netgroup" 2N/A * This code is optimized for lookups by name. 2N/A * For lookups by identifier search key cannot be matched with 2N/A * the name of the "+" or "-" entry. So nss_search() is to be 2N/A * called before extracting the name i.e. via (*be->getnamef)(). 2N/A * But for lookups by name, search key is compared with the name 2N/A * of the "+" or "-" entry to acquire a match and thus 2N/A * unnesessary calls to nss_search() is eliminated. Also for 2N/A * matching "-" entries, calls to nss_search() is eliminated. 2N/A *
colon =
'\0';
/* terminate field to extract name */ 2N/A * The entry is of the form "+@netgroup" or 2N/A * "-@netgroup". If we're performing a lookup by name, 2N/A * we can simply extract the name from the search key 2N/A * (i.e. args->key.name). If not, then we must call 2N/A * nss_search() before extracting the name via the 2N/A * get_XXname() function. i.e. (*be->getnamef)(args). 2N/A /* compare then search */ 2N/A /* need to search for "+" entry */ 2N/A /* search then compare */ 2N/A * The entry is of the form "+" or "-". The former 2N/A * allows all entries from name services. The latter 2N/A * is illegal and ought to be ignored. 2N/A /* need to search for "+" entry */ 2N/A * The entry is of the form "+name" or "-name". 2N/A * If we're performing a lookup by name, we can simply 2N/A * extract the name from the search key 2N/A * (i.e. args->key.name). If not, then we must call 2N/A * nss_search() before extracting the name via the 2N/A * get_XXname() function. i.e. (*be->getnamef)(args). 2N/A /* compare then search */ 2N/A /* need to search for "+" entry */ 2N/A /* search then compare */ 2N/A /* no need to search for "-" entry */ 2N/A * stayopen is set to 0 by default in order to close the opened 2N/A * file. Some applications may break if it is set to 1. 2N/A char *
colon = 0;
/* <=== need comment re lifetime */ 2N/A * assume a NULL buf.result pointer is an indication 2N/A * that the lookup result should be returned in /etc 2N/A * the code executed later needs the result struct 2N/A char *
name;
/* === Need more distinctive label */ 2N/A * In the code below... 2N/A * break means "I found one, I think" (i.e. goto the 2N/A * code after the end of the switch statement), 2N/A * continue means "Next candidate" 2N/A * (i.e. loop around to the switch statement), 2N/A * return means "I'm quite sure" (either Yes or No). 2N/A }
/* Else (silently) ignore the entry */ 2N/A * Normal entry, no +/- nonsense 2N/A * copy string data to 2N/A /* ==> ?? Treat ERANGE differently ?? */ 2N/A /* Skip the offending entry, get next */ 2N/A /* ==> ?? Treat ERANGE differently ?? */ 2N/A name = 0;
/* tell code below we've done the lookup */ 2N/A /* pass "name" variable to code below... */ 2N/A * Do a getXXXnam(name). If we were being pure, 2N/A * we'd introduce yet another function-pointer 2N/A * that the database-specific code had to supply 2N/A * to us. Instead we'll be grotty and hard-code 2N/A * the knowledge that 2N/A * (a) The username is always passwd in key.name, 2N/A * (b) NSS_DBOP_PASSWD_BYNAME == 2N/A * NSS_DBOP_SHADOW_BYNAME == 2N/A * NSS_DBOP_next_iter. 2N/A * Found one via "+", "+name" or "@netgroup". 2N/A * Override some fields if the /etc file says to do so. 2N/A /* ==> ?? Should treat erange differently? */ 2N/A /* 'colon' was set umpteen iterations ago in GETENT_FILE */ 2N/A/* We don't use this directly; we just copy the bits when we want to */ 2N/A/* initialize the variable (in the compat_backend struct) that we do use */ 2N/A }
else {
/* group */