1.5-1 release
[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.51 2005/09/04 03:34:02 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 /* Default initializers */
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        host[MAX_VAL_SIZE];            /* SQL Server to connect to */
212     char        port[MAX_VAL_SIZE];            /* SQL port to connect to */
213     char        socket[MAX_VAL_SIZE];          /* SQL socket path to use */
214     char        username[MAX_VAL_SIZE];        /* Username to connect as */
215     char        password[MAX_VAL_SIZE];        /* Password to connect with */
216     char        database[MAX_VAL_SIZE];        /* SQL Database to open */
217 } sql_server_t;
218
219 typedef struct {
220     sql_query_t     query;
221     sql_server_t    server;
222 } sql_conf_t;
223
224 typedef struct {
225     nboolean        valid;              /* Have we loaded config yet? */
226     sql_conf_t      sql;                /* [server] section */
227 } conf_t;
228
229 #define CONF_INITIALIZER {0}
230
231 /*
232  * As soon as a MySQL link is established, save the results of
233  * getsockname and getpeername here so we can make sure our
234  * socket hasn't been mutilated by an outside program.
235  */
236 typedef struct {
237     struct sockaddr local;              /* getsockname */
238     struct sockaddr remote;             /* getpeername */
239 } socket_info_t;
240
241 /* All information regarding existing MySQL link */
242 typedef struct {
243     nboolean        valid;          /* Are we connected to a server? */
244     MYSQL           link;
245     socket_info_t   sock_info;      /* See above */
246 } con_info_t;
247
248 /* nss_main.c */
249 NSS_STATUS _nss_mysql_init (void);
250 void _nss_mysql_log (int priority, char *fmt, ...);
251 #ifdef HAVE_NSS_COMMON_H
252 NSS_STATUS _nss_mysql_default_destr (nss_backend_t *be, void *args);
253 #endif
254 void _nss_mysql_reset_ent (MYSQL_RES **mresult);
255
256 /* nss_support.c */
257 NSS_STATUS _nss_mysql_load_passwd (void *result, char *buffer, size_t buflen,
258                                    MYSQL_RES *mresult, int *errnop);
259 NSS_STATUS _nss_mysql_load_shadow (void *result, char *buffer, size_t buflen,
260                                    MYSQL_RES *mresult, int *errnop);
261 NSS_STATUS _nss_mysql_load_group (void *result, char *buffer, size_t buflen,
262                                   MYSQL_RES *mresult, int *errnop);
263 NSS_STATUS _nss_mysql_load_gidsbymem (void *result, char *buffer, size_t buflen,
264                                       MYSQL_RES *mresult, int *errnop);
265
266 /* mysql.c */
267 NSS_STATUS _nss_mysql_close_sql (MYSQL_RES **mresult, nboolean graceful);
268 void _nss_mysql_close_result (MYSQL_RES **mresult);
269 NSS_STATUS _nss_mysql_run_query (char *query, MYSQL_RES **mresult,
270                                  int *attempts);
271 NSS_STATUS _nss_mysql_fetch_row (MYSQL_ROW *row, MYSQL_RES *mresult);
272 NSS_STATUS _nss_mysql_escape_string (char *to, const char *from,
273                                      MYSQL_RES **mresult);
274 #define _nss_mysql_num_rows(m) mysql_num_rows (m)
275 #define _nss_mysql_fetch_lengths(m) mysql_fetch_lengths (m)
276 #define _nss_mysql_num_fields(m) mysql_num_fields (m)
277
278 /* nss_config.c */
279 NSS_STATUS _nss_mysql_load_config (void);
280
281 /* lookup.c */
282 NSS_STATUS _nss_mysql_lookup (lookup_t ltype, const char *name,
283                               unsigned int num, char *q, nboolean restricted,
284                               void *result, char *buffer, size_t buflen,
285                               int *errnop,
286                               NSS_STATUS (*load_func)(void *, char *, size_t,
287                                                       MYSQL_RES *, int *),
288                               MYSQL_RES **mresult, const char *caller);
289