[svn-inject] Installing original source of libnss-mysql-bg
[manu/libnss-mysql-bg.git] / src / nss_mysql.h
1 /* Copyright (C) 2002 Ben Goodwin
2    This file is part of the nss-mysql library.
3
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.
8
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
14    You should have received a copy of the GNU General Public License
15    along with the nss-mysql library; if not, write to the Free Software
16    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 /* $Id: nss_mysql.h,v 1.49 2004/11/13 16:25:26 cinergi Exp $ */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #ifdef HAVE_NSS_H
26 #include <nss.h>
27 #elif defined HAVE_NSS_COMMON_H
28 #include <nss_common.h>
29 #include <nss_dbdefs.h>
30 #else
31 #error I need either nss.h or nss_common.h!
32 #endif
33
34 #include <mysql.h>
35
36 #include <sys/socket.h>
37 #include <errno.h>
38
39 #ifdef HAVE_SYSLOG_H
40 #include <syslog.h>
41 #endif
42
43 #include <unistd.h>
44 #include <sys/types.h>
45
46 #ifdef HAVE_STDINT_H
47 #include <stdint.h>
48 #endif
49
50 #include <stdlib.h> /* realloc(), free(), malloc(), atoi() */
51
52 #include <pthread.h>
53
54 #ifdef HAVE_NSS_H
55 #define NSS_SUCCESS     NSS_STATUS_SUCCESS
56 #define NSS_NOTFOUND    NSS_STATUS_NOTFOUND
57 #define NSS_UNAVAIL     NSS_STATUS_UNAVAIL
58 #define NSS_TRYAGAIN    NSS_STATUS_TRYAGAIN
59 typedef enum nss_status NSS_STATUS;
60 #elif defined HAVE_NSS_COMMON_H
61 typedef nss_status_t NSS_STATUS;
62 #define NSS_ARGS(args)  ((nss_XbyY_args_t *)args)
63 #endif
64
65 #define MAX_LINE_SIZE       1024        /* Max line length in config file */
66 #define MAX_QUERY_SIZE      2048        /* Max size of SQL query */
67 #define MAX_NAME_SIZE       128         /* Max username/groupname size */
68 #define MAX_KEY_SIZE        128         /* Max length of a key in cfg file */
69 #define MAX_VAL_SIZE        1024        /* Max length of a val in cfg file */
70 #define MAX_QUERY_ATTEMPTS  3           /* # of query retries */
71
72 /* Use these as defaults until they're overridden via the config file */
73 #define DEF_TIMEOUT     3
74
75 #ifdef DEBUG
76 void _nss_mysql_debug (char *fmt, ...);
77 #define DEBUG_FILE "/tmp/libnss-mysql-debug.log"
78 #define D _nss_mysql_debug
79 #define DN(n) static const char FUNCNAME[] = n;
80 #define DENTER D ("%s: ENTER", FUNCNAME);
81 #define DIRETURN(r) { D ("%s: EXIT (%d)", FUNCNAME, r); return (r); }
82 #define DFRETURN(r)                                                         \
83   {                                                                         \
84     D ("%s: EXIT (%s)", FUNCNAME, r == 0 ? "SUCCESS" : "FAIL");             \
85     return (r);                                                             \
86   }
87 #define DBRETURN(r)                                                         \
88   {                                                                         \
89     D ("%s: EXIT (%s)", FUNCNAME, r == ntrue ? "TRUE" : "FALSE");           \
90     return (r);                                                             \
91   }
92 #define DSRETURN(r)                                                         \
93   {                                                                         \
94     char *status;                                                           \
95     switch (r)                                                              \
96       {                                                                     \
97       case NSS_SUCCESS:                                                     \
98         status = "NSS_SUCCESS";                                             \
99         break;                                                              \
100       case NSS_NOTFOUND:                                                    \
101         status = "NSS_NOTFOUND";                                            \
102         break;                                                              \
103       case NSS_UNAVAIL:                                                     \
104         status = "NSS_UNAVAIL";                                             \
105         break;                                                              \
106       case NSS_TRYAGAIN:                                                    \
107         status = "NSS_TRYAGAIN";                                            \
108         break;                                                              \
109       default:                                                              \
110         status = "UNKNOWN";                                                 \
111         break;                                                              \
112       }                                                                     \
113     D ("%s: EXIT (%s)", FUNCNAME, status);                                  \
114     return (r);                                                             \
115   }
116 #define DPRETURN(r) { D ("%s: EXIT (%p)", FUNCNAME, r); return (r); }
117 #define DRETURN { D ("%s: EXIT", FUNCNAME); return; }
118 #define DEXIT D ("%s: EXIT", FUNCNAME);
119 #else
120 #define D
121 #define DN(n) static const char FUNCNAME[] = n;
122 #define DENTER
123 #define DIRETURN(r) return (r);
124 #define DPRETURN(r) return (r);
125 #define DFRETURN(r) return (r);
126 #define DBRETURN(r) return (r);
127 #define DSRETURN(r) return (r);
128 #define DRETURN return;
129 #define DEXIT
130 #endif
131
132 extern pthread_mutex_t lock;
133 #define LOCK pthread_mutex_lock (&lock)
134 #define UNLOCK pthread_mutex_unlock (&lock)
135
136 /*
137  * Linux and Solaris handle buffer exhaustion differently.
138  * Linux sets errno to ERANGE and returns TRYAGAIN, which results in
139  * the NSS system trying with a buffer twice as big.
140  * Solaris, however, doesn't seem to retry.  I've checked the Solaris 8
141  * code for files/ldap/nisplus NSS and they all set NSS_ARGS(args)->erange
142  * to 1 and return NOTFOUND.  Note that this macro sets *errnop to 1, but
143  * it's not really errnop, it's erange - see the calling functions.
144  * In fact, my tests reveal that if you return TRYAGAIN, Solaris will try
145  * over and over, without increasing the buffer - AKA infinite (or long)
146  * loop.
147  */
148 #ifdef HAVE_NSS_H
149 #define EXHAUSTED_BUFFER                                                     \
150   {                                                                          \
151     *errnop = ERANGE;                                                        \
152     DSRETURN (NSS_TRYAGAIN);                                                 \
153   }
154 #else
155 #define EXHAUSTED_BUFFER                                                     \
156   {                                                                          \
157     if (errnop)                                                              \
158       *errnop = 1;                                                           \
159     DSRETURN (NSS_NOTFOUND);                                                 \
160   }
161 #endif
162
163 /*
164  * To the untrained eye, this looks like my version of a boolean.  It's
165  * really my secret code for taking over the universe ...
166  */
167 typedef enum {
168     nfalse,
169     ntrue
170 } nboolean;
171
172 /*
173  * It's SO damn confusing when functions use a return of 0 for success and
174  * 1 for failure, especially amidst functions that have a boolean return
175  * type.. so use this instead.  PLEASE.  I BEG YOU.
176  */
177 typedef enum {
178     RETURN_SUCCESS,
179     RETURN_FAILURE
180 } freturn_t;
181
182 typedef enum {
183     BYNONE,
184     BYNAME,
185     BYNUM
186 } lookup_t;
187
188 typedef struct {
189     gid_t       **groupsp;
190     long int    group;
191     long int    *start;
192     long int    *size;
193     long int    limit;
194 } group_info_t;
195
196 /* Sql queries to execute for ... */
197 typedef struct {
198     char        getpwuid[MAX_VAL_SIZE];
199     char        getpwnam[MAX_VAL_SIZE];
200     char        getspnam[MAX_VAL_SIZE];
201     char        getpwent[MAX_VAL_SIZE];
202     char        getspent[MAX_VAL_SIZE];
203     char        getgrnam[MAX_VAL_SIZE];
204     char        getgrgid[MAX_VAL_SIZE];
205     char        getgrent[MAX_VAL_SIZE];
206     char        gidsbymem[MAX_VAL_SIZE];       /* list of gids a username belongs to */
207     char        memsbygid[MAX_VAL_SIZE];       /* list of members a gid has */
208 } sql_query_t;
209
210 typedef struct {
211     char        timeout[MAX_VAL_SIZE];         /* Connect timeout in seconds */
212     char        compress[MAX_VAL_SIZE];        /* Use compressed MySQL protocol? */
213     char        initcmd[MAX_VAL_SIZE];         /* Send to server at time of connect */
214 } server_options_t;
215
216 typedef struct {
217     char        host[MAX_VAL_SIZE];            /* SQL Server to connect to */
218     char        port[MAX_VAL_SIZE];            /* SQL port to connect to */
219     char        socket[MAX_VAL_SIZE];          /* SQL socket path to use */
220     char        username[MAX_VAL_SIZE];        /* Username to connect as */
221     char        password[MAX_VAL_SIZE];        /* Password to connect with */
222     char        database[MAX_VAL_SIZE];        /* SQL Database to open */
223     server_options_t options;
224 } sql_server_t;
225
226 typedef struct {
227     sql_query_t     query;
228     sql_server_t    server;
229 } sql_conf_t;
230
231 typedef struct {
232     nboolean        valid;              /* Have we loaded config yet? */
233     sql_conf_t      sql;                /* [server] section */
234 } conf_t;
235
236 #define CONF_INITIALIZER {0}
237
238 /*
239  * As soon as a MySQL link is established, save the results of
240  * getsockname and getpeername here so we can make sure our
241  * socket hasn't been mutilated by an outside program.
242  */
243 typedef struct {
244     struct sockaddr local;              /* getsockname */
245     struct sockaddr remote;             /* getpeername */
246 } socket_info_t;
247
248 /* All information regarding existing MySQL link */
249 typedef struct {
250     nboolean        valid;          /* Are we connected to a server? */
251     MYSQL           link;
252     socket_info_t   sock_info;      /* See above */
253 } con_info_t;
254
255 /* nss_main.c */
256 NSS_STATUS _nss_mysql_init (void);
257 void _nss_mysql_log (int priority, char *fmt, ...);
258 #ifdef HAVE_NSS_COMMON_H
259 NSS_STATUS _nss_mysql_default_destr (nss_backend_t *be, void *args);
260 #endif
261 void _nss_mysql_reset_ent (MYSQL_RES **mresult);
262
263 /* nss_support.c */
264 NSS_STATUS _nss_mysql_load_passwd (void *result, char *buffer, size_t buflen,
265                                    MYSQL_RES *mresult, int *errnop);
266 NSS_STATUS _nss_mysql_load_shadow (void *result, char *buffer, size_t buflen,
267                                    MYSQL_RES *mresult, int *errnop);
268 NSS_STATUS _nss_mysql_load_group (void *result, char *buffer, size_t buflen,
269                                   MYSQL_RES *mresult, int *errnop);
270 NSS_STATUS _nss_mysql_load_gidsbymem (void *result, char *buffer, size_t buflen,
271                                       MYSQL_RES *mresult, int *errnop);
272
273 /* mysql.c */
274 NSS_STATUS _nss_mysql_close_sql (MYSQL_RES **mresult, nboolean graceful);
275 void _nss_mysql_close_result (MYSQL_RES **mresult);
276 NSS_STATUS _nss_mysql_run_query (char *query, MYSQL_RES **mresult,
277                                  int *attempts);
278 NSS_STATUS _nss_mysql_fetch_row (MYSQL_ROW *row, MYSQL_RES *mresult);
279 NSS_STATUS _nss_mysql_escape_string (char *to, const char *from,
280                                      MYSQL_RES **mresult);
281 #define _nss_mysql_num_rows(m) mysql_num_rows (m)
282 #define _nss_mysql_fetch_lengths(m) mysql_fetch_lengths (m)
283 #define _nss_mysql_num_fields(m) mysql_num_fields (m)
284
285 /* nss_config.c */
286 NSS_STATUS _nss_mysql_load_config (void);
287
288 /* lookup.c */
289 NSS_STATUS _nss_mysql_lookup (lookup_t ltype, const char *name,
290                               unsigned int num, char *q, nboolean restricted,
291                               void *result, char *buffer, size_t buflen,
292                               int *errnop,
293                               NSS_STATUS (*load_func)(void *, char *, size_t,
294                                                       MYSQL_RES *, int *),
295                               MYSQL_RES **mresult, const char *caller);
296