summaryrefslogtreecommitdiffstats
path: root/database/eurephiadb_mapping.c
blob: 52c977807c74672769e465a14a9eb41dd668526b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
/* eurephiadb_common.c  --  Common database functions, used by drivers
 *
 *  GPLv2 only - Copyright (C) 2008, 2009
 *               David Sommerseth <dazo@users.sourceforge.net>
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License
 *  as published by the Free Software Foundation; version 2
 *  of the License.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 */

#include <string.h>
#include <assert.h>

#include <libxml/tree.h>

#define EUREPHIADB_MAPPING_C
#include <eurephia_context.h>
#include <eurephia_log.h>
#include <eurephiadb_mapping.h>
#include <eurephia_nullsafe.h>
#include <passwd.h>

// Simple mapping table for table_id to string.  Must match the order of the
// defined tables in eurephia_mapping.h
const char *TABLE_NAME[] = {
        NULL,
        "users",                 // TABLE_USERS
        "certificates",          // TABLE_CERTS
        "usercerts",             // TABLE_USERCERTS
        "lastlog",               // TABLE_LASTLOG
        "attemptslog",           // TABLE_ATTEMPTS
        "blacklist",             // TABLE_BLACKLIST
        "eurephia_adminaccess",  // TABLE_EUREPHIAADMACC
        "firewall_profiles",     // TABLE_FWPROFILES
        NULL};

// Simple mapping table for session status
const char *SESSION_STATUS[] = {
        "UNKNOWN",
        "STARTED",
        "OPEN",
        "CLOSING",
        "CLOSED",
        "CLEANEDUP",
        NULL};


// Extra forward declarations to avoid compiler warnings.  These functions are inline functions
// in eurephia_xml.h, which would then cause multiple declarations of these functions if that
// include file gets included here.
char *xmlGetAttrValue(xmlAttr *properties, const char *key);
char *xmlExtractContent(xmlNode *n);


void eDBfreeMapping(eDBfieldMap *p) {
        if( p == NULL ) {
                return;
        }
        eDBfreeMapping(p->next);

        // Release value and this pointer.
        // Do not attempt to release field_name, as it is a constant char *
        free_nullsafe(NULL, p->value);
        free_nullsafe(NULL, p->table_alias);
        free(p);
}


eDBfieldMap *eDBgetTableFieldMapping(int table) {
        eDBfieldMap *srcmap, *newmap = NULL, *ptr = NULL;
        int i;

        switch( table ) {
        case TABLE_USERS:
                srcmap = eTblMap_user;
                break;

        case TABLE_CERTS:
                srcmap = eTblMap_certificates;
                break;

        case TABLE_LASTLOG:
                srcmap = eTblMap_lastlog;
                break;

        case TABLE_ATTEMPTS:
                srcmap = eTblMap_attempts;
                break;

        case TABLE_BLACKLIST:
                srcmap = eTblMap_blacklist;
                break;

        case TABLE_USERCERTS:
                srcmap = eTblMap_usercerts;
                break;

        case TABLE_EUREPHIAADMACC:
                srcmap = eTblMap_eurephiaadmacc;
                break;

        case TABLE_FWPROFILES:
                srcmap = eTblMap_fwprofiles;
                break;

        default:
                return NULL;
        }

        // Copy the mapping into a pointer chain
        for( i = 0; srcmap[i].field_id != FIELD_NONE; i++ ) {
                ptr = (eDBfieldMap *) malloc_nullsafe(NULL, sizeof(eDBfieldMap)+2);
                assert(ptr != NULL);

                ptr->tableid = srcmap[i].tableid;
                ptr->table_alias = NULL;
                ptr->field_id = srcmap[i].field_id;
                ptr->field_type = srcmap[i].field_type;
                ptr->filter_type = srcmap[i].filter_type;
                ptr->field_name = srcmap[i].field_name;
                ptr->value = NULL;
                ptr->next = newmap;
                newmap = ptr;
        }

        return newmap;
}


inline void eDBcopyMapAttribs(eDBfieldMap *newmap, eDBfieldMap *dbmap, int field) {
        int i = 0;

        for( i = 0; dbmap[i].field_name != NULL; i++ ) {
                if( dbmap[i].field_id == field ) {
                        newmap->field_name = dbmap[i].field_name;
                        if( newmap->field_type != ft_SETNULL ) {
                                newmap->field_type = dbmap[i].field_type;
                        }
                }
        }
}


eDBfieldMap *eDBxmlMapping(eurephiaCTX *ctx, eDBfieldMap *dbmap, const char *tblalias, xmlNode *fmapnode) {
        eDBfieldMap *map = NULL, *ptr = NULL;
        char *fmap_table = NULL;
        xmlNode *nptr = NULL;

        // Check that the node we got is the right one
        if( xmlStrcmp(fmapnode->name, (xmlChar *)"fieldMapping") != 0 ) {
                eurephia_log(ctx, LOG_ERROR, 0, "Invalid fieldMapping XML node");
                return NULL;
        }

        // Make sure the fmapnode is suitable for the given dbmap
        assert( TABLE_NAME[dbmap->tableid] != NULL );
        fmap_table = xmlGetAttrValue(fmapnode->properties, "table");
        if( fmap_table == NULL ) {
                eurephia_log(ctx, LOG_ERROR, 0, "Invalid fieldMapping XML document");
                return NULL;
        }
        if( strcmp(fmap_table, TABLE_NAME[dbmap->tableid]) != 0 ) {
                eurephia_log(ctx, LOG_ERROR, 0, "Mismatch between XML fieldMapping and eDBfieldMap");
                return NULL;
        }

        // Get a copy of the system map
        map = eDBgetTableFieldMapping(dbmap->tableid);

        // Loop through the XML, and register the different values to the system map fields
        nptr = fmapnode->children;
        while( nptr != NULL ) {
                // We are only interested in element nodes
                if( (nptr->type != XML_ELEMENT_NODE) ) {
                        nptr = nptr->next;
                        continue;
                }

                if( nptr->name != NULL ) {
                        int setnull = 0;
                        xmlAttr *atr;
                        char *pwhash = NULL;
                        eDBfieldFilterType filter = flt_NOTSET;

                        // Check attributes given.  Looking for: setnull, pwhash, filter
                        for( atr = nptr->properties; atr != NULL; atr = atr->next ) {
                                if( atr->name == NULL ) {
                                        // Skip nodes without name (just in case)
                                        continue;
                                }
                                if( xmlStrcmp(atr->name, (xmlChar *)"setnull") == 0 ) {
                                        xmlNode *n = atr->children;
                                        setnull = (((n != NULL) && (n->content != NULL)
                                                    && (xmlStrcmp(n->content,(xmlChar *)"1") == 0)) ? 1 : 0);
                                } else if( xmlStrcmp(atr->name, (xmlChar *)"pwhash") == 0 ) {
                                        pwhash = (atr->children != NULL ? (char *) atr->children->content : NULL);
                                } else if( xmlStrcmp(atr->name, (xmlChar *)"filter") == 0 ) {
                                        if( xmlStrcmp(atr->children->content,
                                                      (xmlChar *)"not-equals") == 0 ) {
                                                filter = flt_NEQ;
                                        } else if ( xmlStrcmp(atr->children->content,
                                                              (xmlChar *)"less-than") == 0 ) {
                                                filter = flt_LT;
                                        } else if ( xmlStrcmp(atr->children->content,
                                                              (xmlChar *)"less-than-equals") == 0 ) {
                                                filter = flt_LTE;
                                        } else if ( xmlStrcmp(atr->children->content,
                                                              (xmlChar *)"greater-than") == 0 ) {
                                                filter = flt_GT;
                                        } else if ( xmlStrcmp(atr->children->content,
                                                              (xmlChar *)"greater-than-equals") == 0 ) {
                                                filter = flt_GTE;
                                        } else {
                                                filter = flt_EQ;
                                        }
                                }
                        }

                        // Look up field in our copy of the system map
                        for( ptr = map; ptr != NULL; ptr = ptr->next ) {
                                // If we find the field, copy the value into our map
                                if( xmlStrcmp((xmlChar *)ptr->field_name, nptr->name) == 0 ) {
                                        if( setnull ) {
                                                // If flagged for being set to NULL, change the field type
                                                ptr->field_type = ft_SETNULL;
                                        }

                                        switch( ptr->field_type ) {
                                        case ft_SETNULL:
                                                // Don't set any values if we want to set it to NULL
                                                ptr->value = NULL;
                                                break;

                                        case ft_PASSWD: // If it is a password field type, hash the value
                                                if( (pwhash != NULL) && (strcmp(pwhash, "sha512") == 0) ) {
                                                        ptr->value = (nptr->children != NULL
                                                                      ? (char *)nptr->children->content
                                                                      : strdup(""));
                                                } else {
                                                        // Force hashing of value if it is an unknown hash type
                                                        ptr->value = (nptr->children != NULL
                                                                      ? eurephia_pwd_crypt(ctx,
                                                                                  (char *)nptr->children->content,
                                                                                  NULL)
                                                                      : strdup(""));
                                                }
                                                break;

                                        default:
                                                ptr->value = (nptr->children != NULL
                                                              ? strdup_nullsafe((char *)nptr->children->content)
                                                              : strdup(""));
                                                break;
                                        }
                                        if( filter != flt_NOTSET ) {
                                                ptr->filter_type = filter;
                                        }
                                        break;
                                }
                        }

                        // Go to next XML node
                        nptr = nptr->next;
                } else {
                        eurephia_log(ctx, LOG_ERROR, 0, "*** Illegal XML - unaccepted node: (%i) %s\n",
                                     nptr->type, nptr->name);
                        return NULL;
                }
        }

        for( ptr = map; ptr != NULL; ptr = ptr->next ) {
                // Copy over field name - translated via the db mapping table
                eDBcopyMapAttribs(ptr, dbmap, ptr->field_id);
                // Set correct table alias in the new map
                ptr->table_alias = strdup_nullsafe(tblalias);
        }
        return map;
}


char *eDBmkSortKeyString(eDBfieldMap *tfmap, const char *skeys_str) {
        eDBfieldMap *sk_map = NULL, *ptr1 = NULL;
        int i;
        char *cp = NULL, *tok = NULL, *delims = ",";
        static char sortkeys[8194];

        if( skeys_str == NULL ) {
                return NULL;
        }

        // Make sure we have table field map
        assert( tfmap != NULL );

        // Get the correct table mapping for user input
        sk_map = eDBgetTableFieldMapping(tfmap->tableid);
        assert( sk_map != NULL );

        // Split up the skeys_str (sort keys string) and build up a map
        cp = strdup_nullsafe(skeys_str);
        tok = strtok(cp, delims);
        memset(&sortkeys, 0, 8194);
        while( tok != NULL ) {
                for( ptr1 = sk_map; ptr1 != NULL; ptr1 = ptr1->next) {
                        // If we find the the field in the unified mapping table ...
                        if( strcmp(tok, ptr1->field_name) == 0 ) {
                                // look up the proper field name for the current database
                                for( i = 0; tfmap[i].field_type != FIELD_NONE; i++ ) {
                                        if( ptr1->field_id == tfmap[i].field_id ) {
                                                strncat(sortkeys, tfmap[i].field_name, (8192-strlen(sortkeys)-2));
                                                strcat(sortkeys,",");
                                        }
                                }
                        }
                }
                tok = strtok(NULL, delims);
        }
        free_nullsafe(NULL, cp);
        sortkeys[strlen(sortkeys)-1] = '\0';
        eDBfreeMapping(sk_map);

        return sortkeys;
}

long int eDBmappingFieldsPresent(eDBfieldMap *map) {
        long int ret = 0;
        eDBfieldMap *p = NULL;

        // Loops through all elements and flags those
        // fields with a value set.
        for( p = map; p != NULL; p = p->next ) {
                if( p->value != NULL ) {
                        ret |= p->field_id;
                }
        }
        return ret;
}