1 /* Copyright (C) 2002 Ben Goodwin
2 This file is part of the nss-mysql library.
4 The nss-mysql library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License as published
6 by the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 The nss-mysql library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with the nss-mysql library; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 static const char rcsid[] =
19 "$Id: lookup.c,v 1.28 2004/11/13 18:09:49 cinergi Exp $ ";
21 #include "nss_mysql.h"
22 #include <stdio.h> /* snprintf () */
23 #include <string.h> /* strcpy () */
28 * Take query from config, such as "SELECT x FROM foo WHERE bar = '%s'"
29 * and replace "%s" with appropriate data
30 * ltype = BYNAME, BYNUM, or BYNONE
31 * name = username if this is a BYNAME
32 * num = uid/gid if this is a BYNUM
33 * qin = query in config to use
34 * qout = string to send to MySQL server (after format string processing)
35 * mresult = Current MySQL result (if any)
36 * caller = calling function's name
39 _nss_mysql_build_query (lookup_t ltype, const char *name, unsigned int num,
40 char *qin, char *qout, MYSQL_RES **mresult,
43 DN ("_nss_mysql_build_query")
44 char clean_name[MAX_NAME_SIZE * 2 + 1];
49 /* Verify existence of input query, lest we crash */
52 _nss_mysql_log (LOG_CRIT, "%s has no valid query in config", caller);
53 DSRETURN (NSS_UNAVAIL)
58 case BYNAME: /* This lookup key is a name/string */
59 if (!name || !name[0])
60 DSRETURN (NSS_NOTFOUND)
61 D ("%s: BYNAME, name = '%s'", FUNCNAME, name);
62 if (strlen (name) >= MAX_NAME_SIZE)
64 _nss_mysql_log (LOG_CRIT, "%s: name '%s' too long (MAX = %d)",
65 FUNCNAME, name, MAX_NAME_SIZE);
66 DSRETURN (NSS_UNAVAIL)
68 if (_nss_mysql_escape_string (clean_name, name, mresult) != NSS_SUCCESS)
69 DSRETURN (NSS_UNAVAIL)
70 retVal = snprintf (qout, MAX_QUERY_SIZE, qin, clean_name);
71 if (retVal < 1 || retVal >= MAX_QUERY_SIZE)
73 _nss_mysql_log (LOG_CRIT, "%s: snprintf error: %d", FUNCNAME, retVal);
74 DSRETURN (NSS_UNAVAIL)
76 /* New lookup, reset any existing queries */
77 _nss_mysql_reset_ent (mresult);
79 case BYNUM: /* This lookup key is a uid/gid/number */
80 D ("%s: BYNUM, num = '%u'", FUNCNAME, num);
81 retVal = snprintf (qout, MAX_QUERY_SIZE, qin, num);
82 if (retVal < 1 || retVal >= MAX_QUERY_SIZE)
84 _nss_mysql_log (LOG_CRIT, "%s: snprintf error: %d", FUNCNAME, retVal);
85 DSRETURN (NSS_UNAVAIL)
87 /* New lookup, reset any existing queries */
88 _nss_mysql_reset_ent (mresult);
90 case BYNONE: /* This query has no key (e.g. a getpwent) */
91 D ("%s: BYNONE creating initial query", FUNCNAME);
95 _nss_mysql_log (LOG_ERR, "%s: default case reached - should never happen",
97 DSRETURN (NSS_UNAVAIL)
99 DSRETURN (NSS_SUCCESS)
103 * The high-level function that does the actual lookup
104 * Gets the query built and sent to the MySQL server, as well as
105 * loads the result & buffer with the appropriate return data
107 * ltype = BYNAME, BYNUM, or BYNONE
108 * name = name if BYNAME
109 * num = uid/gid if BYNUM
110 * q = unformatted query from config to use / build from
111 * restricted = restrict this query to euid = 0?
112 * result = NSS API result
113 * buffer = NSS API buffer
114 * buflen = NSS API length of buffer
115 * errnop = NSS API errno pointer
116 * load_func = pointer to function to load result/buffer with
117 * mresult = current MySQL result set
118 * caller = name of calling function
121 _nss_mysql_lookup (lookup_t ltype, const char *name, unsigned int num,
122 char *q, nboolean restricted, void *result,
123 char *buffer, size_t buflen, int *errnop,
124 NSS_STATUS (*load_func)(void *, char *, size_t,
126 MYSQL_RES **mresult, const char *caller)
128 DN ("_nss_mysql_lookup")
129 char query[MAX_QUERY_SIZE]; /* Query to send to MySQL */
131 int attempts = MAX_QUERY_ATTEMPTS; /* Attempt # (countdown) */
132 static uid_t euid = -1; /* Last known euid for change detect */
133 uid_t cur_euid; /* CURRENT euid */
137 cur_euid = geteuid ();
138 D ("%s: restricted = %d, cur_euid = %u", FUNCNAME, restricted, cur_euid);
139 if (restricted == ntrue && cur_euid != 0)
140 DSRETURN (NSS_NOTFOUND)
142 /* Make sure euid hasn't changed, thus changing our access abilities */
145 else if (euid != cur_euid)
147 D ("%s:, euid changed: %u -> %u", FUNCNAME, euid, cur_euid);
148 /* Close MySQL and config to force reload of config and reconnect */
149 _nss_mysql_close_sql (mresult, ntrue);
154 /* Required in case link & config were reset due to euid change */
155 if (_nss_mysql_init () != NSS_SUCCESS)
156 DSRETURN (NSS_UNAVAIL)
158 /* BYNONE indicates *ent; don't create/run the query since we already did */
159 if (!(ltype == BYNONE && mresult && *mresult))
161 /* Create query string using config & args */
162 retVal = _nss_mysql_build_query (ltype, name, num, q, query, mresult,
164 if (retVal != NSS_SUCCESS)
166 retVal = _nss_mysql_run_query (query, mresult, &attempts);
167 if (retVal != NSS_SUCCESS)
171 /* Take result of query and load RESULT & BUFFER */
172 retVal = load_func (result, buffer, buflen, *mresult, errnop);
174 /* BYNONE indicates *ent; don't kill the result here, endent does that */
176 _nss_mysql_close_result (mresult);