eurephiadb_session.c

Go to the documentation of this file.
00001 /* eurephiadb_session.c  --  Functions for handling sessions from eurephia-auth
00002  *
00003  *  GPLv2 only - Copyright (C) 2008 - 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 
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <unistd.h>
00036 
00037 #define EUREPHIA_FWINTF
00038 #include <eurephiafw_struct.h>
00039 #include <eurephia_context.h>
00040 #include "eurephia_nullsafe.h"
00041 #include "eurephia_log.h"
00042 #include "eurephiadb_session.h"
00043 #include <eurephiadb_session_common.h>
00044 #include <environment.h>
00045 #include <randstr.h>
00046 #include <sha512.h>
00047 
00048 
00049 // Also defined in the eurephiadb_driver.h, but not as extern.
00050 extern char *(*eDBget_sessionkey_seed) (eurephiaCTX *ctx, sessionType type, const char *sessionseed);
00051 extern char *(*eDBget_sessionkey_macaddr) (eurephiaCTX *ctx, const char *macaddr);
00052 
00053 extern int (*eDBcheck_sessionkey_uniqueness) (eurephiaCTX *ctx, const char *seskey);
00054 
00055 extern int (*eDBregister_sessionkey) (eurephiaCTX *ctx, const char *seed, const char *seskey);
00056 
00057 extern eurephiaVALUES *(*eDBload_sessiondata) (eurephiaCTX *ctx, const char *sesskey);
00058 
00074 eurephiaSESSION *eDBopen_session_seed(eurephiaCTX *ctx, const char *digest,
00075                                       const char *cname, const char *username,
00076                                       const char *vpnipaddr, const char *vpnipmask,
00077                                       const char *remipaddr, const char *remport)
00078 {
00079         eurephiaSESSION *new_session = NULL;
00080         char *seeddata = NULL, *seed = NULL, *ptr = NULL;
00081         SHA512Context sha;
00082         uint8_t sha_res[SHA512_HASH_SIZE];
00083         size_t totlen = 0, i = 0;
00084 
00085         DEBUG(ctx, 12, "Function call: eDBopen_session_seed(ctx, '%s', '%s', '%s', '%s', '%s', '%s', '%s')",
00086               digest, cname, username, vpnipaddr, vpnipmask, remipaddr, remport);
00087 
00088         new_session = (eurephiaSESSION *) malloc_nullsafe(ctx, sizeof(eurephiaSESSION) + 2);
00089         if( new_session == NULL ) {
00090                 return NULL;
00091         }
00092 
00093         // Session type is stSESSION if we do have VPN address and/or netmask
00094         new_session->type = ((vpnipaddr == NULL) && (vpnipmask == NULL) ? stAUTHENTICATION : stSESSION);
00095 
00096         // Build up a string containing all elements for the session seed
00097         totlen = MAXLEN_TLSDIGEST + MAXLEN_CNAME + MAXLEN_USERNAME + MAXLEN_POOLIPADDR + MAXLEN_POOLNETMASK
00098                 + MAXLEN_TRUSTEDIP + MAXLEN_TRUSTEDPORT + 5 + 15;
00099         // max length of: digest + cname + username + vpnipaddr + vpnipmask
00100         //                + remipaddr + remport + pid + extra buffer
00101 
00102         seeddata = (char *) malloc_nullsafe(ctx, totlen);
00103         if( seeddata == NULL ) {
00104                 free_nullsafe(ctx, new_session);
00105                 return NULL;
00106         }
00107         snprintf(seeddata, totlen, "%.60s%.64s%.34s%.34s%.34s%.34s%.6s%05i",
00108                  digest, cname, username, vpnipaddr, vpnipmask, remipaddr, remport, getpid());
00109 
00110         // Generate a SHA512 version of session seed
00111         memset(&sha, 0, sizeof(SHA512Context));
00112         memset(&sha_res, 0, sizeof(sha_res));
00113         SHA512Init(&sha);
00114         SHA512Update(&sha, seeddata, totlen);
00115         SHA512Final(&sha, sha_res);
00116 
00117         seed = (char *) malloc_nullsafe(ctx, (SHA512_HASH_SIZE*2)+3);
00118         if( seed == NULL ) {
00119                 free_nullsafe(ctx, seeddata);
00120                 free_nullsafe(ctx, new_session);
00121                 return NULL;
00122         }
00123         ptr = seed;
00124 
00125         for( i = 0; i < SHA512_HASH_SIZE; i++ ) {
00126                 sprintf(ptr, "%02x", sha_res[i]);
00127                 ptr += 2;
00128         }
00129         memset(&sha, 0, sizeof(SHA512Context));
00130         memset(&sha_res, 0, sizeof(sha_res));
00131 
00132         DEBUG(ctx, 13, "Using session seed '%s'", seed);
00133 
00134         // Try to retrieve the sessionkey from the database, based on the session seed
00135         new_session->sessionkey = eDBget_sessionkey_seed(ctx, new_session->type, seed);
00136         if( new_session->sessionkey == NULL ) {
00137                 // ... if we do not find a sessionkey ... lets generate one
00138                 int rndlen = 0;
00139                 char *rndstr = NULL;
00140                 char *skeydata = NULL;
00141                 int loop = 0, uniqcheck = 0;
00142 
00143                 DEBUG(ctx, 13, "Unknown session seed, creating new session key");
00144 
00145                 // Loop until we get a unique sessionkey - don't loop more than 10 times
00146                 skeydata = (char *) malloc_nullsafe(ctx, (totlen*2)+4);
00147                 if( skeydata == NULL ) {
00148                         free_nullsafe(ctx, new_session->sessionkey);
00149                         free_nullsafe(ctx, new_session);
00150                         free_nullsafe(ctx, seeddata);
00151                         free_nullsafe(ctx, seed);
00152                         return NULL;
00153                 }
00154                 do {
00155                         memset(skeydata, 0, (totlen*2)+4);
00156 
00157                 // FIXME:  Validate that we have enough random data for the session key
00158 
00159                         // Append some random data to our session seed
00160                         rndstr = (char *) malloc_nullsafe(ctx, (totlen * 2));
00161                         if( rndstr == NULL ) {
00162                                 free_nullsafe(ctx, new_session->sessionkey);
00163                                 free_nullsafe(ctx, new_session);
00164                                 free_nullsafe(ctx, seeddata);
00165                                 free_nullsafe(ctx, seed);
00166                                 return NULL;
00167                         }
00168                         rndlen = ((totlen * 2) - strlen_nullsafe(seed) - 2);
00169 
00170                         if( !eurephia_randstring(ctx, rndstr, rndlen) ) {
00171                                 eurephia_log(ctx, LOG_PANIC, 0,
00172                                              "Could not generate enough random data for session key");
00173                                 free_nullsafe(ctx, new_session->sessionkey);
00174                                 free_nullsafe(ctx, new_session);
00175                                 free_nullsafe(ctx, seeddata);
00176                                 free_nullsafe(ctx, seed);
00177                                 return NULL;
00178                         }
00179 
00180                         // Generate SHA512 version of the session data
00181                         SHA512Init(&sha);
00182                         SHA512Update(&sha, rndstr, rndlen);
00183                         SHA512Final(&sha, sha_res);
00184 
00185                         free_nullsafe(ctx, new_session->sessionkey);
00186                         new_session->sessionkey = (char *) malloc_nullsafe(ctx, (SHA512_HASH_SIZE*2)+3);
00187                         if( new_session->sessionkey == NULL ) {
00188                                 free_nullsafe(ctx, new_session);
00189                                 free_nullsafe(ctx, seeddata);
00190                                 free_nullsafe(ctx, seed);
00191                                 return NULL;
00192                         }
00193 
00194                         ptr = new_session->sessionkey;
00195                         for( i = 0; i < SHA512_HASH_SIZE; i++ ) {
00196                                 sprintf(ptr, "%02x", sha_res[i]);
00197                                 ptr += 2;
00198                         }
00199                         memset(&sha, 0, sizeof(SHA512Context));
00200                         memset(&sha_res, 0, sizeof(sha_res));
00201                         free_nullsafe(ctx, rndstr);
00202 
00203                         loop++;
00204                         uniqcheck = eDBcheck_sessionkey_uniqueness(ctx, new_session->sessionkey);
00205                 } while( (uniqcheck == 0) && loop < 11 );
00206                 free_nullsafe(ctx, skeydata);
00207 
00208                 // If we did not manage to create a unique session key (random data collection must have failed!)
00209                 if( uniqcheck == 0 ) {
00210                         eurephia_log(ctx, LOG_FATAL, 0,
00211                                      "Did not manage to create a unique sessionkey after %i attempts", loop-1);
00212                         free_nullsafe(ctx, new_session->sessionkey);
00213                         free_nullsafe(ctx, new_session);
00214                         free_nullsafe(ctx, seeddata);
00215                         free_nullsafe(ctx, seed);
00216                         return NULL;
00217                 }
00218 
00219                 // Save this session key in the database and connect it to this session seed
00220                 if( eDBregister_sessionkey(ctx, seed, new_session->sessionkey) == 0) {
00221                         eurephia_log(ctx, LOG_FATAL, 0, "Could not register sessionkey");
00222                         free_nullsafe(ctx, new_session->sessionkey);
00223                         free_nullsafe(ctx, new_session);
00224                         free_nullsafe(ctx, seeddata);
00225                         free_nullsafe(ctx, seed);
00226                         return NULL;
00227                 };
00228                 new_session->sessionstatus = SESSION_NEW;
00229         } else {
00230                 new_session->sessionstatus = SESSION_EXISTING;
00231                 DEBUG(ctx, 13, "Session seed found, using sessionkey '%s'", new_session->sessionkey);
00232         }
00233         free_nullsafe(ctx, seed);
00234         free_nullsafe(ctx, seeddata);
00235 
00236         // Load session values from the database
00237         new_session->sessvals = eDBload_sessiondata(ctx, new_session->sessionkey);
00238 
00239         // Return struct which contains session key and session variables
00240         return new_session;
00241 }
00242 
00243 
00255 eurephiaSESSION *eDBopen_session_macaddr(eurephiaCTX *ctx, const char *macaddr) {
00256         eurephiaSESSION *new_session = NULL;
00257 
00258         DEBUG(ctx, 12, "Function call: eDBopen_session_mac(ctx, '%s')", macaddr);
00259 
00260         new_session = (eurephiaSESSION *) malloc_nullsafe(ctx, sizeof(eurephiaSESSION) + 2);
00261         if( new_session == NULL ) {
00262                 return NULL;
00263         }
00264 
00265         new_session->type = stSESSION; // When we have macaddr - this is a stSESSION type of session
00266 
00267         // Get the sessionkey from the database
00268         new_session->sessionkey = eDBget_sessionkey_macaddr(ctx, macaddr);
00269         if( new_session->sessionkey == NULL ) {
00270                 eurephia_log(ctx, LOG_CRITICAL, 0, "Could not find an active session for MAC address '%s'",
00271                              macaddr);
00272                 free_nullsafe(ctx, new_session);
00273                 return NULL;
00274         }
00275         DEBUG(ctx, 13, "Session seed found, using sessionkey '%s'", new_session->sessionkey);
00276 
00277         // Load session values from the database
00278         new_session->sessvals = eDBload_sessiondata(ctx, new_session->sessionkey);
00279 
00280         // Return struct which contains the current session
00281         return new_session;
00282 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines