firewalladmin.c

Go to the documentation of this file.
00001 /* firewalladmin.c  --  Functions for managing firewall profiles
00002  *
00003  *  GPLv2 only - Copyright (C) 2009 - 2010
00004  *               David Sommerseth <dazo@users.sourceforge.net>
00005  *
00006  *  This program is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU General Public License
00008  *  as published by the Free Software Foundation; version 2
00009  *  of the License.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00019  *
00020  */
00021 
00031 #include <string.h>
00032 #include <unistd.h>
00033 #include <assert.h>
00034 
00035 #include <libxml/tree.h>
00036 
00037 #include <sqlite3.h>
00038 
00039 #include <eurephia_nullsafe.h>
00040 #include <eurephia_context.h>
00041 #include <eurephia_log.h>
00042 #include <eurephia_xml.h>
00043 #include <eurephia_values.h>
00044 #include <eurephiadb_session_struct.h>
00045 #include <eurephiadb_mapping.h>
00046 #include <passwd.h>
00047 
00048 #include "../sqlite.h"
00049 
00050 #define FMAP_OVPNACCESSES
00051 #include "../fieldmapping.h"
00052 
00053 
00062 xmlDoc *fwadmin_search(eurephiaCTX *ctx, eDBfieldMap *fmap) {
00063         dbresult *res = NULL;
00064         xmlDoc *doc = NULL;
00065         xmlNode *root_n = NULL, *rec_n = NULL, *acg_n = NULL, *acc_n = NULL, *tmp_n = NULL;
00066         eDBfieldMap *fptr = NULL;
00067         int last_acp = -1, i = 0;
00068 
00069         // Add table alias on the certid, to avoid SQL error
00070         for( fptr = fmap; fptr != NULL; fptr = fptr->next) {
00071                 switch( fptr->field_id ) {
00072                 case FIELD_CERTID:
00073                         fptr->table_alias = strdup("c");
00074                 default:
00075                         break;
00076                 }
00077         }
00078 
00079         // Query the database for accesses
00080         res = sqlite_query_mapped(ctx, SQL_SELECT,
00081                                   "SELECT access_descr, fw_profile, accessprofile, "
00082                                   "       uid, username, "
00083                                   "       uac.certid, common_name, organisation, "
00084                                   "       email, lower(digest), c.registered, uicid "
00085                                   "  FROM openvpn_accesses"
00086                                   "  LEFT JOIN openvpn_usercerts uac USING (accessprofile)"
00087                                   "  LEFT JOIN openvpn_users USING (uid)"
00088                                   "  LEFT JOIN openvpn_certificates c ON (uac.certid = c.certid)",
00089                                   NULL, fmap, "accessprofile, uid, c.certid");
00090         if( res == NULL ) {
00091                 eurephia_log(ctx, LOG_ERROR, 0, "Error querying the database for firewall profiles");
00092                 return NULL;
00093         }
00094 
00095         eurephiaXML_CreateDoc(ctx, 1, "firewall_profiles", &doc, &root_n);
00096         xmlNewProp(root_n, (xmlChar *) "mode", (xmlChar *) "profiles");
00097 
00098         for( i = 0; i < sqlite_get_numtuples(res); i++ ) {
00099                 xmlChar *tmp = NULL;
00100                 if( last_acp != atoi_nullsafe(sqlite_get_value(res, i, 2)) ) {
00101                         // Create a new block element when we get a new uid
00102                         rec_n = xmlNewChild(root_n, NULL, (xmlChar *) "profile", NULL);
00103                         sqlite_xml_value(rec_n, XML_ATTR, "accessprofile", res, i, 2);
00104                         sqlite_xml_value(rec_n, XML_NODE, "description", res, i, 0);
00105                         sqlite_xml_value(rec_n, XML_NODE, "firewall_destination", res, i, 1);
00106                         acg_n = xmlNewChild(rec_n, NULL, (xmlChar *) "granted_accesses", NULL);
00107 
00108                         last_acp = atoi_nullsafe(sqlite_get_value(res, i, 2));
00109                 }
00110 
00111                 // Only continue populating acc_n tags if we have some access info available
00112                 if( sqlite_get_value(res, i, 11) == NULL ) {
00113                         continue;
00114                 }
00115 
00116                 acc_n = xmlNewChild(acg_n, NULL, (xmlChar *) "access", NULL);
00117                 sqlite_xml_value(acc_n, XML_ATTR, "uicid", res, i, 11);
00118                 tmp_n = sqlite_xml_value(acc_n, XML_NODE, "username", res, i, 4);
00119                 sqlite_xml_value(tmp_n, XML_ATTR, "uid", res, i, 3);
00120 
00121                 tmp_n = xmlNewChild(acc_n, NULL, (xmlChar *) "certificate", NULL);
00122                 // Only populate tags with certificate info if we have certificate info available
00123                 if( sqlite_xml_value(tmp_n, XML_ATTR, "certid", res, i, 5) ) {
00124                         sqlite_xml_value(tmp_n, XML_ATTR, "registered", res, i, 10);
00125 
00126                         // OpenVPN uses underscore as default value for "unsafe" characters
00127                         // in X509 fields.  Replace with space for better readability.
00128                         tmp = (xmlChar *)sqlite_get_value(res, i, 6);
00129                         xmlReplaceChars(tmp, '_', ' ');
00130                         xmlNewChild(tmp_n, NULL, (xmlChar *) "common_name", tmp);
00131 
00132                         tmp = (xmlChar *)sqlite_get_value(res, i, 7);
00133                         xmlReplaceChars(tmp, '_', ' ');
00134                         xmlNewChild(tmp_n, NULL, (xmlChar *) "organisation", tmp);
00135 
00136                         sqlite_xml_value(tmp_n, XML_NODE, "email", res, i, 8);
00137                         sqlite_xml_value(tmp_n, XML_NODE, "digest", res, i, 9);
00138                 }
00139         }
00140         sqlite_free_results(res);
00141         return doc;
00142 }
00143 
00144 
00153 xmlDoc *fwadmin_add(eurephiaCTX *ctx, eDBfieldMap *fmap) {
00154         dbresult *res = NULL;
00155         xmlDoc *ret = NULL;
00156 
00157         // Check if we have the needed fields, and only the needed fields
00158         if( eDBmappingFieldsPresent(fmap) != (FIELD_DESCR | FIELD_FWPROFILE) ) {
00159                 return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL,
00160                                              "Adding firewall profile only accepts "
00161                                              "description and firewall profile fields");
00162         }
00163 
00164         res = sqlite_query_mapped(ctx, SQL_INSERT, "INSERT INTO openvpn_accesses", fmap, NULL, NULL);
00165         if( res == NULL ) {
00166                 eurephia_log(ctx, LOG_FATAL, 0, "Could not register the new firewall profile");
00167                 ret = eurephiaXML_ResultMsg(ctx, exmlERROR, NULL,
00168                                             "Could not register the new firewall profile");
00169         } else {
00170                 ret = eurephiaXML_ResultMsg(ctx, exmlRESULT, NULL,
00171                                             "Firewall profile registered with id %i",
00172                                             res->last_insert_id);
00173         }
00174         sqlite_free_results(res);
00175         return ret;
00176 }
00177 
00178 
00187 xmlDoc *fwadmin_delete(eurephiaCTX *ctx, eDBfieldMap *fmap) {
00188         dbresult *res = NULL;
00189         xmlDoc *ret = NULL;
00190         long int fields;
00191 
00192         // Check if we have the needed fields, and only the needed fields
00193         fields = eDBmappingFieldsPresent(fmap);
00194         if( !(fields & FIELD_FWPROFILE) && !(fields & FIELD_RECID) ) {
00195                 return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL,
00196                                              "Deleting firewall profile only accepts "
00197                                              "firewall profile and destination fields");
00198         }
00199 
00200         // Find the accessprofile ID based on the fieldmap
00201         res = sqlite_query_mapped(ctx, SQL_SELECT, "SELECT DISTINCT accessprofile FROM openvpn_accesses",
00202                                   NULL, fmap, NULL);
00203         if( res == NULL ) {
00204                 eurephia_log(ctx, LOG_FATAL, 0, "Could not delete the firewall profile (1)");
00205                 return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Could not delete the firewall profile");
00206         }
00207 
00208         // Delete all references to this access profile in openvpn_usercerts
00209         if( sqlite_get_numtuples(res) > 0 ) {
00210                 dbresult *dres = NULL;
00211                 int i = 0;
00212 
00213                 for( i = 0; i < sqlite_get_numtuples(res); i++ ) {
00214                         dres = sqlite_query(ctx,
00215                                             "DELETE FROM openvpn_usercerts "
00216                                             "      WHERE accessprofile = %q",
00217                                             sqlite_get_value(res, i, 0));
00218                         if( dres == NULL ) {
00219                                 eurephia_log(ctx, LOG_FATAL, 0, "Could not delete the firewall profile (2)");
00220                                 ret = eurephiaXML_ResultMsg(ctx, exmlERROR, NULL,
00221                                                             "Could not delete the firewall profile");
00222                                 sqlite_free_results(res);
00223                                 return ret;
00224                         }
00225                         sqlite_free_results(dres);
00226                 }
00227         }
00228 
00229         // Delete requested access profiles from openvpn_accesses
00230         res = sqlite_query_mapped(ctx, SQL_DELETE, "DELETE FROM openvpn_accesses", NULL, fmap, NULL);
00231         if( res == NULL ) {
00232                 eurephia_log(ctx, LOG_FATAL, 0, "Could not delete the firewall profile");
00233                 ret = eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Could not delete the firewall profile");
00234         } else {
00235                 ret = eurephiaXML_ResultMsg(ctx, exmlRESULT, NULL, "Firewall profile deleted");
00236         }
00237         sqlite_free_results(res);
00238         return ret;
00239 }
00240 
00241 
00245 xmlDoc *eDBadminFirewallProfiles(eurephiaCTX *ctx, xmlDoc *xmlqry) {
00246         eDBfieldMap *fmap = NULL;
00247         char *mode = NULL;
00248         xmlDoc *resxml = NULL;
00249         xmlNode *root_n = NULL, *fieldmap_n = NULL;
00250 
00251         DEBUG(ctx, 20, "Function call: eDBadminFirewallProfiles(ctx, {xmlDoc})");
00252         assert( (ctx != NULL) && (xmlqry != NULL) );
00253 
00254         if( (ctx->context_type != ECTX_ADMIN_CONSOLE) && (ctx->context_type != ECTX_ADMIN_WEB) ) {
00255                 eurephia_log(ctx, LOG_CRITICAL, 0,
00256                              "eurephia admin function call attempted with wrong context type");
00257                 return NULL;
00258         }
00259 
00260         root_n = eurephiaXML_getRoot(ctx, xmlqry, "firewall_profiles", 1);
00261         if( root_n == NULL ) {
00262                 eurephia_log(ctx, LOG_CRITICAL, 0, "Invalid XML input.");
00263                 return NULL;
00264         }
00265         mode = xmlGetAttrValue(root_n->properties, "mode");
00266         if( mode == NULL ) {
00267                 eurephia_log(ctx, LOG_ERROR, 0, "Missing mode attribute");
00268                 return NULL;
00269         }
00270 
00271         fieldmap_n = xmlFindNode(root_n, "fieldMapping");
00272         if( fieldmap_n == NULL ) {
00273                 eurephia_log(ctx, LOG_ERROR, 0, "Missing fieldMapping");
00274         }
00275         fmap = eDBxmlMapping(ctx, tbl_sqlite_openvpnaccesses, NULL, fieldmap_n);
00276 
00277         if( strcmp(mode, "search") == 0 ) {
00278                 resxml = fwadmin_search(ctx, fmap);
00279         } else if( strcmp(mode, "add") == 0 ) {
00280                 resxml = fwadmin_add(ctx, fmap);
00281         } else if( strcmp(mode, "delete") == 0 ) {
00282                 resxml = fwadmin_delete(ctx, fmap);
00283         } else {
00284                 eurephia_log(ctx, LOG_ERROR, 0, "FirewallProfiles - Unknown mode: '%s'", mode);
00285                 resxml = eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Unknown mode '%s'", mode);
00286         }
00287         eDBfreeMapping(fmap);
00288         return resxml;
00289 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines